5 detyra tipike në intervistat për JavaScript: analiza dhe zgjidhje

5 detyra tipike në intervistat për JavaScript: analiza dhe zgjidhje

Nga përkthyesi: kemi publikuar për ju një artikull i Marisë Perna, i cili flet për detyrat standarde të JavaScript, që zakonisht ofrohen për aplikantët-programues në intervista. Artikulli do të jetë i dobishëm, kryesisht për programuesit e rinj.

Intervistat në kompanitë teknologjike prej kohësh kanë qenë një temë diskutimi. Nuk ka çfarë të habitemi — kalimi i suksesshëm i intervistës ofron mundësinë për të siguruar një punë të mirë. Por nuk është aq e lehtë, pasi shpeshherë nevojitet të zgjidhni probleme të komplikuara.

Më së shumti, shumica e këtyre problemeve nuk kanë lidhje me punën që do të kryejë aplikanti, por duhet prapë t'i zgjidhni ato. N sometimes, duhet t'i zgjidhni ato në një tablo, pa kontrolluar me Google ose ndonjë burim tjetër. Po, situata gradualisht po ndryshon, dhe në disa kompani po hiqet dorë nga këto intervista, por shumë punëdhënës vazhdojnë të qëndrojnë pas kësaj tradite. Ky artikull i kushtohet shqyrtimit të detyrave standarde të JavaScript, të cilat përdoren shpesh si detyra për aplikantët.

Kujtojmë: për të gjithë lexuesit e «Habra» — zbritje prej 10,000 rublesh për regjistrimin në çdo kurs Skillbox me kodin promovues «Habr».

Skillbox rekomandon: Kurs praktik «Mobil developer PRO».

E rëndësishme është përgatitja e kujdesshme për intervistën tuaj

Po, para se të filloni të shqyrtoni detyrat, le të shqyrtojmë këshillat e përgjithshme për përgatitjen për intervistën.

E rëndësishme është të përgatiteni paraprakisht. Kontrolloni se sa mirë i mbani mend algoritmet dhe strukturat e të dhënave, dhe forconi njohuritë tuaja në ato fusha që nuk janë shumë të njohura për ju. Ka shumë platforma online që mund t'ju ndihmojnë të përgatiteni për intervistat. Këshillojmë GeeksforGeeks, Pramp, Interviewing.io dhe CodeSignal.

Duhet të mësoni të shprehni zgjidhjen me zë. Preferohet të flisni me aplikantët për atë që po bëni, dhe jo thjesht të shkruani në tablo (ose të shkruani kod në kompjuter, gjithashtu në heshtje). Kështu, nëse bëni një gabim në kod, por mënyra e zgjidhjes është përgjithësisht e saktë, mund të rrisni shanset tuaja për sukses.

Duhet ta kuptoni detyrën para se të filloni zgjidhjen. Në disa raste, mund të kuptoni sipërfaqësisht detyrën dhe pastaj të shkoni në një drejtim të gabuar. Mund të vlejë të bëni disa pyetje sqaruese intervistuesit.

Duhet të ushtroni të shkruani kod me dorë, dhe jo në PC. Në intervistat, ndonjëherë kandidatëve u jepet një marker dhe një tabelë pa asnjë udhëzues ose formatim automatik. Kur kërkoni zgjidhje, është mirë të shkruani kodin tuaj në një copë letër ose në tabelë. Nëse mbani gjithçka në mendje, mund të harroni diçka të rëndësishme.

Detyrat model në JavaScript

Mundësisht disa nga këto detyra ju janë të njohura. Ju ose keni kaluar intervista ku duhet të zgjidhni diçka të ngjashme, ose keni praktikuar ato gjatë studimit të JavaScript. Tani është koha të zgjidhni ato përsëri, përfshirë një shpjegim të hollësishëm të procesit.

Palindrom

Palindromi është një fjalë, një fjali ose një renditje simbolet që lexohen në të njëjtën mënyrë si në drejtim të zakonshëm ashtu edhe në të kundërt. Për shembull, “Anna” është një palindrom, ndërsa “table” dhe “John” nuk janë.

Shtrimi

E dhënë një varg; duhet të shkruani një funksion që kthen vlerën true nëse vargu është palindrom dhe false nëse nuk është. Duhet të merrni parasysh hapësirat dhe shenjat e pikësimit.

palindrome(‘racecar’) === true
palindrome(‘table’) === false

Analizojmë detyrën

Ideja kryesore këtu është të ktheni vargun në drejtimin e kundërt. Nëse vargu “i kthyer” është plotësisht identik me origjinalin, atëherë kemi një palindrom dhe funksioni duhet të kthejë vlerën true. Ndryshe, false.

Zgjidhja

Ja kodi që lejon zgjidhjen e palindromit.

const palindrome = str => {
  // kthe vargun në shkronja të vogla
  str = str.toLowerCase()
  // kthe vargun hyrës dhe kthe rezultatin e
  // krahasimit
  return str === str.split('').reverse().join('')
}

Hapi i parë është të konvertoni karakteret e vargut hyrës në shkronja të vogla. Kjo është një garanci që programi do të krahasojë pikërisht vetë karakteret, jo regjistrin ose diçka tjetër.

Hapi i dytë është të kthehet vargu. Kjo nuk është e vështirë: duhet ta ktheni atë në një array përmes metodës .split() (biblioteka String). Më pas e kthejmë array-n duke përdorur .reverse() (biblioteka Array). Hapi final është të kthejmë array-n e kthyer në varg me .join() (biblioteka Array).

Tani, gjithçka që duhet të bëni është të krahasoni vargun “e kthyer” me origjinalin, duke kthyer rezultatin true ose false.

FizzBuzz

Një nga detyrat më të njohura në intervista.

Shtrimi

Duhet të shkruani një funksion që nxjerr në konsolë numrat nga 1 deri në n, ku n është një numër i plotë që funksioni e merr si parametër, me këto kushte:

  • të nxjerrë fizz në vend të numrave që janë të shumëfishueshëm me 3;
  • shfaqja e buzz në vend të numrave që janë të shumëfish të 5;
  • shfaqja e fizzbuzz në vend të numrave që janë të shumëfish të 3 dhe 5.

Shembulli

Fizzbuzz(5)

Rezultati

// 1
// 2
// fizz
// 4
// buzz

Analizojmë detyrën

E rëndësishme këtu është mënyra e gjetjes së numrave të shumëfishme duke përdorur JavaScript. Kjo mund të realizohet duke përdorur operatorin e mod dhe ose mbetje — %, i cili tregon mbetjen gjatë ndarjes së dy numrave. Nëse mbetja është 0, kjo do të thotë se numri i parë është i shumëfishmë me numrin e dytë.

12 % 5 // 2 -> 12 nuk është i shumëfishmë me 5
12 % 3 // 0 -> 12 është i shumëfishmë me 3

Kështu, nëse ndajmë 12 me 5, marrim 2 me mbetje 2. Nëse ndajmë 12 me 3, marrim 4 me mbetje 0. Në rastin e parë, 12 nuk është i shumëfishmë me 5, në rastin e dytë — 12 është i shumëfishmë me 3.

Zgjidhja

Zgjidhja më e mirë do të jetë kodi si vijon:

const fizzBuzz = num => {
  for(let i = 1; i <= num; i++) {
    // kontroloni nëse numri është i shumëfishmë me 3 dhe 5
    if(i % 3 === 0 && i % 5 === 0) {
      console.log('fizzbuzz')
    } // kontrolloni nëse numri është i shumëfishmë me 3
      else if(i % 3 === 0) {
      console.log('fizz')
    } // kontrolloni nëse numri është i shumëfishmë me 5
      else if(i % 5 === 0) {
      console.log('buzz')
    } else {
      console.log(i)
    }
  }
}

Funksioni kryen kontrollin e nevojshëm duke përdorur operatorët kushtorë dhe jep rezultatin e kërkuar për përdoruesin. Në këtë detyrë duhen kushtuar vëmendje rendit të operatorëve if…else: filloni me kushtin e dyfishtë (&&) dhe përfundojini me rastin kur nuk mund të gjejmë numra të shumëfishmë. Si rezultat, ne mbulim të gjitha rastet.

Anagram

Kështu quhet një fjalë që përmban të gjitha shkronjat e një fjale tjetër në të njëjtën sasi, por në një rend tjetër.

Shtrimi

Duhet të shkruani një funksion që kontrollon nëse dy fjalitë janë anagramë, duke mos marrë në konsideratë regjistrin e shkronjave. Merren parasysh vetëm simbolet; hapësirat ose shenjat e pikës nuk merren në konsideratë.

anagram('finder', 'Friend') -> true
anagram('hello', 'bye') -> false

Analizojmë detyrën

Këtu është e rëndësishme të merren parasysh të gjitha shkronjat në të dy fjalitë hyrëse dhe numri i tyre në secilën fjalë.

finder -> f: 1 friend -> f: 1
i: 1 r: 1
n: 1 i: 1
d: 1 e: 1
e: 1 n: 1
r: 1 d: 1

Për ruajtjen e të dhënave të anagramës, duhet të zgjidhet një strukturë si literal objekt JavaScript. Çelësi në këtë rast është simboli i shkronjës, vlera është numri i përsëritjeve të saj në fjalinë aktuale.

Ka edhe kushte të tjera:

  • Duhet të sigurohemi që regjistri i shkronjave në krahasim të mos merret parasysh. Thjesht shndërrojmë të dy fjalitë në shkronja të vogla ose të mëdha.
  • Përjashtojmë nga krahasimi të gjitha jo-simbolet. Më mirë është të punojmë me shprehje normale.

Zgjidhja

// helper function that builds the
// object to store the data
const buildCharObject = str => {
  const charObj = {}
  for(let char of str.replace(/[^w]/g).toLowerCase()) {
    // if the object has already a key value pair
    // equal to the value being looped over,
    // increase the value by 1, otherwise add
    // the letter being looped over as key and 1 as its value
    charObj[char] = charObj[char] + 1 || 1
  }
  return charObj
}
 
// main function
const anagram = (strA, strB) => {
  // build the object that holds strA data
  const aCharObject = buildCharObject(strA)
  // build the object that holds strB data
  const bCharObject = buildCharObject(strB)
 
  // compare number of keys in the two objects
  // (anagrams must have the same number of letters)
  if(Object.keys(aCharObject).length !== Object.keys(bCharObject).length) {
    return false
  }
  // if both objects have the same number of keys
  // we can be sure that at least both strings
  // have the same number of characters
  // now we can compare the two objects to see if both
  // have the same letters in the same amount
  for(let char in aCharObject) {
    if(aCharObject[char] !== bCharObject[char]) {
      return false
    }
  }
  // if both the above checks succeed,
  // you have an anagram: return true
  return true
}

Kujdesi në përdorimin e Object.keys() në snippet-in lart. Ky metod kthen një array që përmban emrat ose çelësat në të njëjtin rend siç shfaqen në objekt. Në këtë rast, array do të jetë kështu:

[‘f’, ‘i’, ‘n’, ‘d’, ‘e’, ‘r’]

Kështu, ne marrim vetitë e objektit pa pasur nevojë të ekzekutojmë një cikël të gjatë. Në këtë detyrë mund të përdoret ky metod me vetinë .length — për të kontrolluar nëse të dy stringat kanë të njëjtin numër karakteresh — kjo është një veçori e rëndësishme për anagramet.

Gjetja e tingujve të theksuar

Një detyrë mjaft e thjeshtë, e cila shpesh shfaqet në intervista.

Shtrimi

Duhet të shkruani një funksion që merr një string si argument dhe kthen numrin e tingujve që ndodhen në string.
Tingujt e theksuar janë "a", "e", "i", "o", "u".

Shembulli:

findVowels(‘hello’) // —> 2
findVowels(‘why’) // —> 0

Zgjidhja

Ja varianti më i thjeshtë:

const findVowels = str => {
  let count = 0
  const vowels = ['a', 'e', 'i', 'o', 'u']
  for(let char of str.toLowerCase()) {
    if(vowels.includes(char)) {
      count++
    }
  }
  return count
}

Është e rëndësishme të vëmë re përdorimin e metodës .includes(). Ajo është e aksesueshme edhe për stringa, edhe për array. Duhet ta aplikoni për të zbuluar nëse një array përmban një vlerë të caktuar. Kjo metodë kthen true, nëse array përmban vlerën e specifikuar, dhe false, nëse jo.

Ka edhe një zgjidhje më të shkurtër për problemin:

const findVowels = str => {
  const matched = str.match(/[aeiou]/gi)
  return matched ? matched.length : 0
}

Këtu përdoret metoda .match(), e cila lejon realizimin e një kërkimi efektiv. Nëse një shprehje e rregullt si argument i metodës zbulohet brenda stringut të specifikuar, atëherë vlera që kthehet është një array i simboleve të përputhura. Ndërsa nëse nuk ka përputhje, .match() kthen null.

Fibonacci

Një detyrë klasike që mund të takoni në intervista të niveleve të ndryshme. Duhet kujtuar se sekuenca e Fibonacci-t është një radhë numrash ku çdo numër i mëpasshëm është shuma e dy numrave të mëparshëm. Kështu, dhjetë numrat e parë paraqiten kështu: 0, 1, 1, 2, 3, 5, 8, 13, 21, 34.

Shtrimi

Duhet të shkruani një funksion që kthen regjistrimin n në një sekuencë të caktuar, ku n është numri që kalon si argument në funksion.

fibonacci(3) // —> 2

Kjo detyrë përfshin kalimin nëpër cikël një numër të caktuar herësh, siç është specifikuar në argument, duke kthyer vlerën në pozitat përkatëse. Ky lloj formimi i detyrës kërkon përdorimin e cikleve. Nëse në vend të kësaj përdorni rekursivitetin, kjo mund t'i pëlqejë intervistuesit dhe t'ju japë disa pikë shtesë.

Zgjidhja

const fibonacci = num => {
  // ruaj sekuencën Fibonacci që po
  // do ta gjenerosh brenda një array dhe
  // inicializo array-n me dy numrat e parë
  // të sekuencës
  const result = [0, 1]
 
  for(let i = 2; i <= num; i++) {
    // shto shumen e dy numrave
    // që paraprijnë pozitat e i në array-n rezultat
    // në fund të array-it rezultat
    const prevNum1 = result[i - 1]
    const prevNum2 = result[i - 2]
    result.push(prevNum1 + prevNum2)
  }
  // kthe vlerën e fundit në array-in rezultat
  return result[num]
}

Në array-in rezultat, dy numrat e parë ndodhen në rresht, pasi çdo regjistrim në sekuencë përbëhet nga shuma e dy numrave të mëparshëm. Në fillim të dy numrave, që mund të merren për të prodhuar numrin e ardhshëm, nuk ka, kështu që cikli nuk arrin t'i gjenerojë ato automatikisht. Por, siç e dimë, dy numrat e parë janë gjithmonë 0 dhe 1. Prandaj, mund ta inicializojmë array-in rezultat manualisht.

Sa i përket rekursivitetit, këtu është më e thjeshtë dhe më e komplikuar njëkohësisht:

const fibonacci = num => {
  // nëse numri është ose 0 ose 1 kthe numrin
  if(num < 2) {
    return num
  }
  // rekursivitet këtu
  return fibonacci(num - 1) + fibonacci(num - 2)
}

Ne vazhdojmë të thërrasim fibonacci(), duke kaluar numra gjithnjë e më të vegjël si argumente. Ndaluar kur argumenti i kaluar është 0 ose 1.

Përfundimi

Probabilisht, ju keni hasur në ndonjë nga këto detyra, nëse keni kaluar intervista për pozita si zhvillues frontend ose JavaScript (veçanërisht nëse është niveli junior). Por nëse ato nuk ju kanë rënë, mund të jenë të dobishme në të ardhmen — gjithsesi për zhvillimin tuaj të përgjithshëm.

Skillbox rekomandon:

Burimi: habr.com

Blini hostim të besueshëm për faqe interneti me mbrojtje DDoS, serverë VPS VDS 🔥 Blini hostim të besueshëm për faqe interneti me mbrojtje DDoS, serverë VPS VDS - ProHoster