5 detyrave tipike në intervistat për JavaScript: analiza dhe zgjidhjet

5 detyrave tipike në intervistat për JavaScript: analiza dhe zgjidhjet

Nga përkthyesi: publikuam për ju një artikull nga Maria Perna (Maria Antonietta Perna), e cila flet për detyrat tipike në JavaScript, që zakonisht ofrohen për kandidatët zhvillues në intervista. Artikulli do të jetë i dobishëm, para së gjitha, për programuesit e rinj.

Intervistat nĂ« kompanitĂ« teknologjike kanĂ« kohĂ« qĂ« janĂ« bĂ«rĂ« njĂ« legjendĂ«. Nuk ka çudi pĂ«r kĂ«tĂ« — kalimi me sukses i njĂ« interviste jep mundĂ«sinĂ« pĂ«r tĂ« marrĂ« njĂ« punĂ« tĂ« mirĂ«. Por nuk Ă«shtĂ« aq e thjeshtĂ«, pasi shpeshherĂ« Ă«shtĂ« e nevojshme tĂ« zgjidhen detyra tĂ« komplikuara.

Ndërsa shumica e këtyre detyrave shpesh nuk kanë lidhje me punën që do të kryejë kandidati, ato megjithatë duhet zgjidhur. Ndonjëherë duhet t'i zgjidhni ato në një tabu, pa kontrolluar në Google ose ndonjë burim tjetër. Po, situata gradualisht po ndryshon, dhe në disa kompani po hiqen dorë nga këto intervista, por shumë punëdhënës ende e mbajnë këtë traditë. Ky artikull është dedikuar analizës së detyrave tipike JavaScript, të cilat përdoren shpesh si detyra për kandidatët.

KujtojmĂ«: pĂ«r tĂ« gjithĂ« lexuesit e "Habra" — zbritje prej 10,000 rublej pĂ«r regjistrimin nĂ« çdo kurs Skillbox me kodin promocional "Habr".

Skillbox rekomandon: Kurs praktik «Programues i celularëve PRO».

E rëndësishme është të përgatiteni me kujdes për intervistën tuaj.

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

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

ËshtĂ« mirĂ« tĂ« mĂ«soni tĂ« flisni zĂ«shĂ«m pĂ«r zgjidhjen. Preferohet tĂ« tregoni se çfarĂ« po bĂ«ni, dhe jo thjesht tĂ« shkruani nĂ« tabllo (ose tĂ« shkruani kod nĂ« kompjuter, gjithashtu nĂ« heshtje). NĂ« kĂ«tĂ« mĂ«nyrĂ«, nĂ«se bĂ«ni njĂ« gabim nĂ« kod, por mĂ«nyra e zgjidhjes Ă«shtĂ« pĂ«rgjithĂ«sisht e saktĂ«, mund tĂ« rrisni mundĂ«sitĂ« tuaja pĂ«r sukses.

Duhet ta mendoni problemin, para se të filloni ta zgjidhni. Në disa raste, mund të kuptoni sipërfaqësisht detyrën dhe më pas të ndiheni në një udhë të gabuar. Ndoshta do të ishte mirë të bëni disa pyetje sqaruese për intervistuesin.

Duhet tĂ« stĂ«rviteni nĂ« shkrimin e kodit me dorĂ«, dhe jo nĂ« PC. HerĂ« pas here, gjatĂ« intervista, kĂ«rkuesi i punĂ«s merr njĂ« marker dhe njĂ« tabelĂ« qĂ« s’ka as sugjerime, as formatim automatik. Kur kĂ«rkoni zgjidhje, Ă«shtĂ« mirĂ« ta shkruani kodin tuaj nĂ« njĂ« letĂ«r ose drejtpĂ«rdrejt nĂ« tabelĂ«. NĂ«se e mbani gjithçka nĂ« kokĂ«, mund tĂ« haroni diçka tĂ« rĂ«ndĂ«sishme.

Detyrat standarde në JavaScript

Padyshim, disa nga këto detyra janë tashmë të njohura për ju. Ju ose keni kaluar nëpër intervista ku duhej të zgjidhnit diçka të ngjashme, ose keni praktikuar ato gjatë studimit të JavaScript. Tani ka ardhur koha për t'i zgjidhur ato përsëri, përveç me një shpjegim të detajuar të procesit.

Palindromi

Palindromi Ă«shtĂ« njĂ« fjalĂ«, fjali ose sekuencĂ« simboresh qĂ« lexohet nĂ« mĂ«nyrĂ« identike nga tĂ« dyja drejtimet. PĂ«r shembull, “Anna” Ă«shtĂ« njĂ« palindrom, ndĂ«rsa “table” dhe “John” nuk janĂ«.

Formulimi

I është dhënë një varg; duhet të shkruani një funksion që kthen vlerën true nëse vargu është një palindrom, dhe false nëse nuk është. Në këtë rast, duhet të merrni parasysh hapsirat dhe shenjat e pikësimit.

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

Analizojmë detyrën

Ideja kryesore Ă«shtĂ« tĂ« kthejmĂ« stringun pĂ«rmbys. NĂ«se stringu "i kthyer" Ă«shtĂ« plotĂ«sisht identik me origjinalin, atĂ«herĂ« kemi njĂ« palindrom dhe funksioni duhet tĂ« kthejĂ« vlerĂ«n true. NĂ« rast se jo — false.

Zgjidhja

Ja kodi që lejon zgjidhjen e palindromëve.

const palindrome = str => {
  // kthe stringun në shkronja të vogla
  str = str.toLowerCase()
  // kthe stringun e hyrjes përmbys dhe kthe rezultatin e
  // krahasimit
  return str === str.split('').reverse().join('')
}

Hapi i parë është të konvertojmë karakteret e stringut të hyrjes në shkronja të vogla. Kjo garanton që programi do të krahasojë pikërisht karakteret, jo rastësinë ose diçka tjetër.

Hapi i dytĂ« Ă«shtĂ« tĂ« kthejmĂ« stringun pĂ«rmbys. KĂ«tĂ« nuk Ă«shtĂ« e vĂ«shtirĂ« ta bĂ«jmĂ«: duhet ta konvertojmĂ« atĂ« nĂ« njĂ« array pĂ«rmes metodĂ«s .split() (biblioteka String). Pastaj ne e kthejmĂ« array-nĂ«, duke pĂ«rdorur .reverse() (biblioteka Array). Hapi pĂ«rfundimtar — tĂ« kthejmĂ« array-nĂ« pĂ«r tĂ« kthyer nĂ« string pĂ«rmes .join() (biblioteka Array).

Tani, gjithçka që duhet të bëjmë është të krahasojmë stringun "e kthyer" me origjinalin, duke kthyer rezultatin true ose false.

FizzBuzz

Një nga detyrat më të popullarizuara në intervistat.

Formulimi

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

  • printo fizz nĂ« vend tĂ« numrave qĂ« janĂ« shumĂ«fish tĂ« 3;
  • printo buzz nĂ« vend tĂ« numrave qĂ« janĂ« shumĂ«fish tĂ« 5;
  • printo fizzbuzz nĂ« vend tĂ« numrave qĂ« janĂ« shumĂ«fish tĂ« 3 dhe tĂ« 5.

Shembuj

Fizzbuzz(5)

Rezultati

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

Analizojmë detyrën

E rëndësishme këtu është mënyra e gjetjes së numrave shumëfish me përdorimin e JavaScript. Kjo mund të realizohet me operatorin e modulusit ose mbetje - %, i cili tregon mbetjen kur ndahen dy numra. Nëse mbetja është 0, kjo do të thotë se numri i parë është shumëfish i numrit të dytë.

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

Pra, nĂ«se ndajmĂ« 12 me 5, marrim 2 me mbetje 2. NdĂ«rsa nĂ«se ndajmĂ« 12 me 3, marrim 4 me mbetje 0. NĂ« rastin e parĂ« 12 nuk Ă«shtĂ« shumĂ«fish i 5, nĂ« rastin e dytĂ« — 12 Ă«shtĂ« shumĂ«fish i 3.

Zgjidhja

Zgjidhja optimale do të jetë kodi i mëposhtëm:

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

Funksioni kryen kontrollet e nevojshme duke pĂ«rdorur operatorĂ«t kushtorĂ« dhe kthen rezultatin e nevojshĂ«m pĂ«r pĂ«rdoruesin. NĂ« kĂ«tĂ« detyrĂ«, duhet t’i kushtohet vĂ«mendje rendit tĂ« operatorĂ«ve if
else: tĂ« fillohet me kushtin e dyfishtĂ« (&&) dhe tĂ« pĂ«rfundohet me rastin kur nuk janĂ« gjetur numra shumĂ«fish. Si rezultat, mbulojmĂ« tĂ« gjitha variacionet.

Anagram

Ky është një fjalë që përmban të gjitha shkronjat e një fjale tjetër në të njëjtin numër, por në rend tjetër.

Formulimi

Duhet të shkruani një funksion që kontrollon nëse dy fjalitë janë anagram, ku rastësia e shkronjave nuk ka rëndësi. Merren parasysh vetëm simbolet; hapësirat ose shenjat e pikësimit nuk merren parasysh.

anagram(‘finder’, ‘Friend’) —> true
anagram(‘hello’, ‘bye’) —> false

Analizojmë detyrën

Këtu është e rëndësishme të merret në konsideratë se duhet të kontrolloni çdo shkronjë në dy fjalitë hyrëse dhe numrin e 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Ă« anagramit duhet tĂ« zgjidhet njĂ« strukturĂ« si literal objekt i 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 siguruar qĂ« regjistri i shkronjave nuk merret parasysh nĂ« krahasim. Thjesht do t'i transformojmĂ« tĂ« dyja stringjet nĂ« shkronja tĂ« vogla ose tĂ« mĂ«dha.
  • E pĂ«rjashtojmĂ« nga krahasimi tĂ« gjitha karakteret qĂ« nuk janĂ« simbole. MĂ« mirĂ« do tĂ« punojmĂ« me shprehje rĂ©guliere.

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 me përdorimin e Object.keys() në shembullin e mësipërm. Ky metod kthen një array që përmban emrat ose çelësat në të njëjtin rend që ndodhen në objekt. Në këtë rast, array do të jetë si më poshtë:

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

NĂ« kĂ«tĂ« mĂ«nyrĂ«, marrim pronat e objektit pa nevojĂ«n pĂ«r tĂ« bĂ«rĂ« njĂ« cikĂ«l tĂ« gjatĂ«. NĂ« projekt, mund tĂ« pĂ«rdoret ky metod me pronĂ«n .length — pĂ«r tĂ« verifikuar nĂ«se tĂ« dyja stringjet kanĂ« tĂ« njĂ«jtin numĂ«r karakteresh — kjo Ă«shtĂ« njĂ« veçori e rĂ«ndĂ«sishme e anagramĂ«ve.

Kërkimi i zanoreve

Një detyrë mjaft e thjeshtë që shpesh përballet në intervista.

Formulimi

Duhet të shkruhet një funksion që merr një string si argument dhe kthen numrin e zanoreve që përmbajnë stringu.
Zanoret janë "a", "e", "i", "o", "u".

Shembuj:

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

Zgjidhja

Ja versioni 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Ă« theksohet pĂ«rdorimi i metodĂ«s .includes(). Ajo Ă«shtĂ« e disponueshme si pĂ«r string-at, ashtu edhe pĂ«r array-t. Duhet tĂ« pĂ«rdoret pĂ«r tĂ« pĂ«rcaktuar nĂ«se array-i pĂ«rmban njĂ« vlerĂ« tĂ« caktuar. Kjo metodĂ« kthen true nĂ«se array-i pĂ«rmban vlerĂ«n e caktuar, 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 ? matches.length : 0
}

Këtu përdoret metoda .match(), e cila lejon realizimin e një kërkimi efikas. Nëse shprehja e rregullt si argument i metodës zbulon diçka brenda string-ut të caktuar, vlera e kthyer bëhet një array i simboleve të përputhura. Ndërsa, nëse nuk ka përputhje, .match() kthen null.

Fibonaçi

Një problem klasik që mund të takoni në intervista të nivelit të ndryshëm. Vlen të theksohet se seria e Fibonaçit është një rresht numrash, ku çdo numër i ardhshëm është shuma e dy numrave të mëparshëm. Kështu, dhjetë numrat e parë duken si më poshtë: 0, 1, 1, 2, 3, 5, 8, 13, 21, 34.

Formulimi

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

fibonacci(3) // —> 2

Ky detyrĂ« pĂ«rfshin kalimin pĂ«rmes njĂ« cikli kaq shumĂ« herĂ« sa Ă«shtĂ« e specifikuar nĂ« argument, duke kthyer vlerĂ«n nĂ« pozitat pĂ«rkatĂ«se. Ky mĂ«nyrĂ« e formulimit tĂ« detyrĂ«s kĂ«rkon pĂ«rdorimin e cikleve. NĂ«se pĂ«rdorni rekursivitet nĂ« vend, kjo mund t’i pĂ«lqejĂ« intervistuesit dhe t’ju japĂ« disa pikĂ« shtesĂ«.

Zgjidhja

const fibonacci = num => {
  // ruani sekuencën Fibonacci që do
  // të gjeneroni brenda një array dhe
  // inicializoni arrayn me dy
  // numrat e parë të sekuencës
  const result = [0, 1]
 
  for(let i = 2; i <= num; i++) {
    // shtoni shumën e dy numrave
    // që paraprijnë pozitën e i në arrayn e rezultatit
    // në fund të arrayn e rezultatit
    const prevNum1 = result[i - 1]
    const prevNum2 = result[i - 2]
    result.push(prevNum1 + prevNum2)
  }
  // kthej vlerën e fundit në arrayn e rezultatit
  return result[num]
}

Në array-n e rezultateve, dy numrat e parë ndodhen në rresht, pasi secili regjistrim në sekuencë përbëhet nga shuma e dy numrave të mëparshëm. Në fillim të dy numrave, të cilët mund të merren për të marrë numrin tjetër, nuk ka, prandaj cikli nuk mund t'i gjenerojë ato në mënyrë automatike. Por, siç e dimë, dy numrat e parë janë gjithmonë 0 dhe 1. Prandaj, mund ta inicializojmë array-n e rezultateve manualisht.

Sa i përket rekursionit, këtu gjithçka është më e thjeshtë dhe më e komplikuar në të njëjtën kohë:

const fibonacci = num => {
  // nëse numri është ose 0 ose 1 kthe numrin
  if(num < 2) {
    return num
  }
  // rekursioni 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ërfundim

Me siguri ju tashmĂ« keni hasur ndonjĂ« nga detyrat e pĂ«rmendura, nĂ«se keni kaluar intervista pĂ«r punĂ« si zhvillues frontend ose JavaScript (sidomos nĂ«se Ă«shtĂ« niveli junior). Por nĂ«se ato nuk ju kanĂ« rĂ«nĂ«, ato mund tĂ« jenĂ« tĂ« dobishme nĂ« tĂ« ardhmen — minimalisht pĂ«r zhvillim tĂ« pĂ«rgjithshĂ«m.

Skillbox rekomandon:

Burimi: habr.com

Bleni hostim tĂ« besueshĂ«m pĂ«r faqe me mbrojtje nga DDoS, serverĂ« VPS VDS đŸ”„ Bleni hostim tĂ« besueshĂ«m pĂ«r faqe me mbrojtje nga DDoS, serverĂ« VPS VDS | ProHoster