Live Coding

Nesnenin Boş Olup Olmadığını Kontrol Et

Bir JavaScript nesnesinin boş olup olmadığını nasıl kontrol edersiniz?

Açıklama: Bir nesne, kendi numaralandırılabilir özelliklerine sahip değilse boştur. Verilen bir nesnenin kendi numaralandırılabilir özellik adlarının bir dizisini döndüren Object.keys(obj)'yi kullanabiliriz. Bu dizinin uzunluğu 0 ise, nesne boştur.

function isEmpty(obj) {   return Object.keys(obj).length === 0; } console.log(isEmpty({})); // true console.log(isEmpty({ a: 1 })); // false

Bir Dizeyi Ters Çevir

Verilen bir dizeyi tersine çeviren bir fonksiyon yazın.

Açıklama: En basit yol, dizeyi karakter dizisine dönüştürmek, diziler için yerleşik reverse() metodunu kullanmak ve ardından karakterleri tekrar bir dizeye birleştirmektir.

function reverseString(str) {   return str.split('').reverse().join(''); } console.log(reverseString('hello')); // 'olleh'

Palindrom Kontrolü

Verilen bir dizenin palindrom olup olmadığını kontrol eden bir fonksiyon yazın.

Açıklama: Palindrom, ileri ve geri aynı okunan bir kelime veya ifadedir. Bunu, dizeyi tersine çevirerek (daha sağlam bir kontrol için büyük/küçük harf ve alfanümerik olmayan karakterleri göz ardı ederek, ancak burada basit bir kontrol yapıyoruz) ve orijinaliyle karşılaştırarak kontrol edebiliriz.

function isPalindrome(str) {   const reversed = str.split('').reverse().join('');   return str === reversed; } console.log(isPalindrome('racecar')); // true console.log(isPalindrome('hello')); // false

Bir Dizideki En Büyük Sayıyı Bul

Sayı dizisindeki en büyük sayıyı bulan bir fonksiyon yazın.

Açıklama: Dizi üzerinde yineleme yaparak, şimdiye kadar bulunan en büyük sayıyı takip edebilirsiniz. Alternatif olarak, dizi öğelerini argüman olarak geçirmek için Math.max() fonksiyonunu yayılma sözdizimi (...) ile birlikte kullanabilirsiniz.

function findMaxNumber(arr) {   if (arr.length === 0) return undefined; // Veya hata fırlat   return Math.max(...arr); } console.log(findMaxNumber([1, 5, 2, 9, 3])); // 9

FizzBuzz

1'den n'ye kadar sayıları yazdıran bir program yazın. Ancak üç katı olanlar için sayının yerine 'Fizz' yazdırın ve beş katı olanlar için 'Buzz' yazdırın. Hem üç hem de beşin katı olan sayılar için 'FizzBuzz' yazdırın.

Açıklama: Bu klasik problem, temel döngü ve koşullu mantığı test eder. 1'den n'ye kadar yinelemeniz ve 3 ve 5'e bölünebilirliği kontrol etmek için modül operatörünü (%) kullanmanız gerekir.

function fizzBuzz(n) {   for (let i = 1; i <= n; i++) {     if (i % 3 === 0 && i % 5 === 0) {       console.log('FizzBuzz');     } else if (i % 3 === 0) {       console.log('Fizz');     } else if (i % 5 === 0) {       console.log('Buzz');     } else {       console.log(i);     }   } } fizzBuzz(15);

Diziden Tekrarlananları Kaldır

Bir diziden tekrarlanan öğeleri kaldıran bir fonksiyon yazın.

Açıklama: Bunu başarmak için modern ve kısa bir yol, bir Set kullanmaktır. Set'ler yalnızca benzersiz değerler saklar. Diziyi bir Set'e ve ardından tekrar bir diziye dönüştürebilirsiniz.

function removeDuplicates(arr) {   return [...new Set(arr)]; } console.log(removeDuplicates([1, 2, 2, 3, 4, 4, 5])); // [1, 2, 3, 4, 5]

Anagram Kontrolü

İki dizenin birbirinin anagramı olup olmadığını kontrol eden bir fonksiyon yazın.

Açıklama: Anagramlar, başka bir kelimenin harflerinin yeniden düzenlenmesiyle oluşan kelimelerdir. Kontrol etmek için dizeleri temizleyebilir, sıralayabilir ve karşılaştırabiliriz. Temizleme, alfanümerik olmayan karakterleri kaldırmayı ve tutarlı bir büyük/küçük harfe dönüştürmeyi içerir.

function isAnagram(str1, str2) {   const clean = (str) => str.replace(/[^a-z0-9]/gi, '').toLowerCase();   const sorted = (str) => clean(str).split('').sort().join('');     return sorted(str1) === sorted(str2); } console.log(isAnagram('listen', 'silent')); // true console.log(isAnagram('hello', 'world')); // false

Faktöriyel Hesapla

Negatif olmayan bir tam sayının faktöriyelini hesaplayan bir fonksiyon yazın.

Açıklama: Bir sayının faktöriyeli (n!), n'den küçük veya n'ye eşit tüm pozitif tam sayıların çarpımıdır. Bunu, 1'den n'ye kadar sayıları çarparak yinelemeli olarak hesaplayabiliriz.

function factorial(n) {   if (n < 0) return undefined; // Faktöriyel negatif sayılar için tanımlı değildir   if (n === 0) return 1;   let result = 1;   for (let i = 1; i <= n; i++) {     result *= i;   }   return result; } console.log(factorial(5)); // 120

Dizideki Tüm Sayıları Topla

Bir dizideki tüm sayıların toplamını döndüren bir fonksiyon yazın.

Açıklama: Bir diziden tek bir değer biriktirmek için ideal olan reduce metodunu kullanabilirsiniz. Bir geri çağırma fonksiyonu ve bir başlangıç değeri (toplama için 0) alır.

function sumArray(arr) {   return arr.reduce((accumulator, currentValue) => accumulator + currentValue, 0); } console.log(sumArray([1, 2, 3, 4])); // 10

İç İçe Diziyi Düzleştir

İç içe bir diziyi düzleştiren bir fonksiyon yazın. Basitlik için, yalnızca bir seviye iç içe olduğunu varsayın.

Açıklama: Tek bir iç içe seviye için, yayılma operatörüyle Array.prototype.concat() veya flat() metodunu (ES2019) kullanabilirsiniz.

function flattenArray(arr) {   // flat() kullanarak (ES2019+ uygunsa daha basit)   // return arr.flat();   // reduce ve concat kullanarak   return arr.reduce((acc, val) => acc.concat(val), []); } console.log(flattenArray([1, [2, 3], 4, [5]])); // [1, 2, 3, 4, 5]

Bir Dizedeki Sesli Harfleri Say

Verilen bir dizedeki sesli harflerin (a, e, i, o, u) sayısını bulan bir fonksiyon yazın.

Açıklama: Dize üzerinde (büyük/küçük harf duyarsız) yineleyin ve her karakterin bir sesli harf olup olmadığını kontrol edin. Bir sayacı tutun.

function countVowels(str) {   const vowels = 'aeiou';   let count = 0;   for (let char of str.toLowerCase()) {     if (vowels.includes(char)) {       count++;     }   }   return count; } console.log(countVowels('Hello World')); // 3

Cümleyi Başlık Büyük Harfe Dönüştür

Bir cümleyi başlık büyük harfe (her kelimenin ilk harfi büyük) dönüştüren bir fonksiyon yazın.

Açıklama: Cümleyi kelimelere ayırın, ardından her kelime üzerinde yineleyin, ilk harfi büyük yapın ve geri kalanını küçük yapın. Son olarak, kelimeleri tekrar birleştirin.

function titleCase(str) {   return str.toLowerCase().split(' ').map(word => {     return word.charAt(0).toUpperCase() + word.slice(1);   }).join(' '); } console.log(titleCase('i am a little tea pot')); // 'I Am A Little Tea Pot'

İki Sayı Problemi

Bir tamsayılar dizisi nums ve bir tamsayı target verildiğinde, toplamları target olan iki sayının dizinlerini döndürün.

Açıklama: Yaygın bir yaklaşım, yineleme yaparken sayıları ve dizinlerini depolamak için bir hash haritası (veya bir JavaScript nesnesi) kullanmaktır. Her sayı için, target - mevcut_sayı'nın haritada olup olmadığını kontrol edin.

function twoSum(nums, target) {   const map = {};   for (let i = 0; i < nums.length; i++) {     const complement = target - nums[i];     if (map[complement] !== undefined) {       return [map[complement], i];     }     map[nums[i]] = i;   }   return []; // Veya null, veya çözüm yoksa hata fırlat } console.log(twoSum([2, 7, 11, 15], 9)); // [0, 1]

Kapanışlar Kullanarak Bir Sayaç Uygula

Bir sayaç fonksiyonu döndüren bir fonksiyon oluşturun. Döndürülen fonksiyon her çağrıldığında, bir sayıyı artırmalı ve döndürmelidir.

Açıklama: Bu, kapanışları gösterir. İç fonksiyon, dış fonksiyonun yürütmesi bittikten sonra bile dış fonksiyonun kapsamındaki count değişkenine erişebilir.

function createCounter() {   let count = 0;   return function() {     count++;     return count;   }; } const counter1 = createCounter(); console.log(counter1()); // 1 console.log(counter1()); // 2 const counter2 = createCounter(); console.log(counter2()); // 1

İlk Tekrarlamayan Karakteri Bul

Bir dizideki ilk tekrarlamayan karakteri bulan bir fonksiyon yazın.

Açıklama: Karakter frekanslarını saymak için bir hash haritası kullanabilirsiniz. İlk olarak, frekans haritasını oluşturmak için dize üzerinde yineleyin. Ardından, dize üzerinde tekrar yineleyin ve sayısı 1 olan ilk karakteri döndürün.

function firstNonRepeatingChar(str) {   const charCount = {};   for (const char of str) {     charCount[char] = (charCount[char] || 0) + 1;   }   for (const char of str) {     if (charCount[char] === 1) {       return char;     }   }   return null; // Veya hepsi tekrar ediyorsa bir gösterge } console.log(firstNonRepeatingChar('aabbcdeeff')); // 'c' console.log(firstNonRepeatingChar('swiss')); // 'w'

Dizi Parçalama

Bir diziyi belirtilen boyutta gruplara ayıran bir fonksiyon yazın.

Açıklama: Diziyi yineleyin, belirtilen boyutta dilimler alın ve bunları yeni bir diziye itin. Son parçanın daha küçük olabileceği durumu ele alın.

function chunkArray(arr, size) {   const chunked = [];   let index = 0;   while (index < arr.length) {     chunked.push(arr.slice(index, index + size));     index += size;   }   return chunked; } console.log(chunkArray([1, 2, 3, 4, 5, 6, 7], 3)); // [[1, 2, 3], [4, 5, 6], [7]]

Sayı Asal mı Kontrol Et

Verilen bir sayının asal sayı olup olmadığını belirleyen bir fonksiyon yazın.

Açıklama: Asal sayı, 1'den büyük, kendisinden ve 1'den başka pozitif böleni olmayan doğal bir sayıdır. 2'den sayının kareköküne kadar yineleyin, bölünebilirliği kontrol edin. 1 ve 2 gibi uç durumları ele alın.

function isPrime(num) {   if (num <= 1) return false;   if (num <= 3) return true;   if (num % 2 === 0 || num % 3 === 0) return false;   for (let i = 5; i * i <= num; i = i + 6) {     if (num % i === 0 || num % (i + 2) === 0) return false;   }   return true; } console.log(isPrime(7)); // true console.log(isPrime(10)); // false

Bir Dizedeki En Uzun Kelimeyi Bul

Bir cümledeki en uzun kelimeyi bulan bir fonksiyon yazın.

Açıklama: Dizeyi kelime dizisine ayırın. Ardından, dizide yineleyin, şimdiye kadar bulunan en uzun kelimeyi (veya uzunluğunu) takip edin.

function findLongestWord(str) {   const words = str.split(' ');   let longestWord = '';   for (const word of words) {     // Gerekirse kelimeleri temizle (örn. noktalama işaretlerini kaldır)     if (word.length > longestWord.length) {       longestWord = word;     }   }   return longestWord; } console.log(findLongestWord('The quick brown fox jumped over the lazy dog')); // 'jumped'

`Array.prototype.map` Uygulayın

Array.prototype.map fonksiyonunun kendi sürümünüzü uygulayın.

Açıklama: map fonksiyonu bir geri çağırma alır ve orijinal dizinin her öğesine geri çağırmayı uygulayarak yeni bir dizi oluşturur. Fonksiyonunuz dizide yinelemeli ve yeni diziyi oluşturmalıdır.

function myMap(arr, callback) {   const mappedArray = [];   for (let i = 0; i < arr.length; i++) {     mappedArray.push(callback(arr[i], i, arr));   }   return mappedArray; } const numbers = [1, 4, 9]; const roots = myMap(numbers, Math.sqrt); console.log(roots); // [1, 2, 3]

`Array.prototype.filter` Uygulayın

Array.prototype.filter fonksiyonunun kendi sürümünüzü uygulayın.

Açıklama: filter fonksiyonu bir geri çağırma alır ve sağlanan geri çağırma fonksiyonu tarafından uygulanan testi geçen tüm öğelerle yeni bir dizi oluşturur.

function myFilter(arr, callback) {   const filteredArray = [];   for (let i = 0; i < arr.length; i++) {     if (callback(arr[i], i, arr)) {         filteredArray.push(arr[i]);     }   }   return filteredArray; } const words = ['spray', 'limit', 'elite', 'exuberant', 'destruction', 'present']; const result = myFilter(words, word => word.length > 6); console.log(result); // ['exuberant', 'destruction', 'present']

`Array.prototype.reduce` Uygulayın

Array.prototype.reduce fonksiyonunun kendi sürümünüzü uygulayın.

Açıklama: reduce fonksiyonu, dizinin her öğesi üzerinde kullanıcı tarafından sağlanan bir 'reducer' geri çağırma fonksiyonunu yürütür ve önceki öğe üzerindeki hesaplamadan dönen değeri iletir. Reducer'ın dizinin tüm öğelerinde çalıştırılmasının nihai sonucu tek bir değerdir. Başlangıç değeri argümanını ele alın.

function myReduce(arr, callback, initialValue) {   let accumulator = initialValue;   let startIndex = 0;   if (initialValue === undefined) {       if (arr.length === 0) throw new TypeError('Boş dizide başlangıç değeri olmadan reduce');       accumulator = arr[0];       startIndex = 1;   }   for (let i = startIndex; i < arr.length; i++) {     accumulator = callback(accumulator, arr[i], i, arr);   }   return accumulator; } const array1 = [1, 2, 3, 4]; const sum = myReduce(array1, (acc, curr) => acc + curr, 0); console.log(sum); // 10

Memorizasyon - Fibonacci Dizisi

Performansı optimize etmek için memorizasyon kullanarak bir Fibonacci fonksiyonu uygulayın.

Açıklama: Fibonacci dizisi tekrarlanan hesaplamalar içerir. Memorizasyon, pahalı fonksiyon çağrılarının sonuçlarını saklar ve aynı girdiler tekrar oluştuğunda önbelleğe alınmış sonucu döndürür.

function memoizedFib() {   const cache = {};   function fib(n) {     if (n in cache) {       return cache[n];     }     if (n <= 1) {       return n;     }     const result = fib(n - 1) + fib(n - 2);     cache[n] = result;     return result;   }   return fib; } const fibonacci = memoizedFib(); console.log(fibonacci(10)); // 55 console.log(fibonacci(40)); // 102334155 (memorizasyon yapılmayandan çok daha hızlı)

Dengeli Parantezleri Kontrol Et

Parantez içeren bir dizenin {}[]() dengeli olup olmadığını kontrol eden bir fonksiyon yazın.

Açıklama: Bir yığın kullanın. Açılış paranteziyle karşılaştığınızda, onu yığına itin. Kapanış paranteziyle karşılaştığınızda, yığının boş olup olmadığını veya en üstteki öğenin eşleşen açılış parantezi olup olmadığını kontrol edin. Eşleşiyorsa, yığını çıkarın. Aksi takdirde veya yığın boşsa, dengesizdir. Sonunda, boş bir yığın dengeli olduğu anlamına gelir.

function isBalanced(str) {   const stack = [];   const map = { '(': ')', '{': '}', '[': ']' };   for (let char of str) {     if (map[char]) {       stack.push(char);     } else if (Object.values(map).includes(char)) {       if (stack.length === 0) return false;       const lastOpen = stack.pop();       if (map[lastOpen] !== char) return false;     }   }   return stack.length === 0; } console.log(isBalanced('({[]})')); // true console.log(isBalanced('([)]')); // false

Basit Bir Kuyruk Uygula

enqueue (arkaya ekle) ve dequeue (önden kaldır) metodlarıyla bir Kuyruk veri yapısı uygulayın.

Açıklama: Bir kuyruk, İlk Giren İlk Çıkar (FIFO) prensibini takip eder. enqueue için push ve dequeue için shift ile bir dizi kullanılabilir.

class Queue {   constructor() {     this.items = [];   }   enqueue(element) {     this.items.push(element);   }   dequeue() {     if (this.isEmpty()) return 'Yetersiz akış';     return this.items.shift();   }   front() {     if (this.isEmpty()) return 'Kuyrukta eleman yok';     return this.items[0];   }   isEmpty() {     return this.items.length === 0;   } } const q = new Queue(); q.enqueue(10); q.enqueue(20); console.log(q.dequeue()); // 10 console.log(q.front()); // 20

Basit Bir Yığın Uygula

push (üste ekle) ve pop (üstten kaldır) metodlarıyla bir Yığın veri yapısı uygulayın.

Açıklama: Bir yığın, Son Giren İlk Çıkar (LIFO) prensibini takip eder. push ve pop metodlarıyla bir dizi kullanılabilir.

class Stack {   constructor() {     this.items = [];   }   push(element) {     this.items.push(element);   }   pop() {     if (this.isEmpty()) return 'Yetersiz akış';     return this.items.pop();   }   peek() {     return this.items[this.items.length - 1];   }   isEmpty() {     return this.items.length === 0;   } } const s = new Stack(); s.push(10); s.push(20); console.log(s.pop()); // 20 console.log(s.peek()); // 10

Sıradaki Eksik Sayıyı Bul

0, 1, 2, ..., n sayılarından alınan n farklı sayıyı içeren bir dizi verildiğinde, dizide eksik olanı bulun.

Açıklama: 0'dan n'ye kadar olan sayıların toplamı n*(n+1)/2 formülü kullanılarak hesaplanabilir. Dizideki öğelerin gerçek toplamı hesaplanabilir. Bu iki toplam arasındaki fark, eksik sayı olacaktır.

function findMissingNumber(nums) {   const n = nums.length;   const expectedSum = n * (n + 1) / 2;   const actualSum = nums.reduce((sum, num) => sum + num, 0);   return expectedSum - actualSum; } console.log(findMissingNumber([3, 0, 1])); // 2 console.log(findMissingNumber([9, 6, 4, 2, 3, 5, 7, 0, 1])); // 8

Debounce Fonksiyonu

Bir debounce fonksiyonu uygulayın. Debouncing, bir fonksiyonun belirli bir süre çağrılmadıkça tekrar çağrılmamasını sağlar.

Açıklama: setTimeout ve clearTimeout kullanın. Debounce edilen fonksiyon her çağrıldığında, önceki zaman aşımını temizleyin ve yeni bir tane ayarlayın. Asıl fonksiyon çağrısı yalnızca zaman aşımı tamamlandığında gerçekleşir.

function debounce(func, delay) {   let timeoutId;   return function(...args) {     clearTimeout(timeoutId);     timeoutId = setTimeout(() => {       func.apply(this, args);     }, delay);   }; } // Örnek kullanım: const sayHello = () => console.log('Merhaba!'); const debouncedHello = debounce(sayHello, 1000); debouncedHello(); // 1 saniye sonra çağrılır (tekrar çağrılmazsa) debouncedHello(); // Zamanlayıcıyı sıfırlar debouncedHello(); // Zamanlayıcıyı sıfırlar, bu çağrıdan 1 saniye sonra çalışır.

Throttle Fonksiyonu

Bir throttle fonksiyonu uygulayın. Throttling, bir fonksiyonun belirtilen bir zaman aralığında en fazla bir kez çağrılmasını sağlar.

Açıklama: Bir çağrının izinli olup olmadığını belirtmek için bir bayrak kullanın. Çağrıldığında, izinliyse fonksiyonu yürütün, bayrağı false olarak ayarlayın ve aralıktan sonra bayrağı sıfırlamak için setTimeout kullanın.

function throttle(func, limit) {   let inThrottle = false;   return function(...args) {     if (!inThrottle) {       func.apply(this, args);       inThrottle = true;       setTimeout(() => inThrottle = false, limit);     }   }; } // Örnek kullanım: const logScroll = () => console.log('Kaydırılıyor...'); const throttledScroll = throttle(logScroll, 1000); // window.addEventListener('scroll', throttledScroll); // Saniyede en fazla bir kez loglayacaktır.

Curry Fonksiyonu

İki argüman alan bir fonksiyonu alan ve onun curried bir versiyonunu döndüren bir fonksiyon yazın.

Açıklama: Currying, birden çok argüman alan bir fonksiyonu, her biri tek bir argüman alan bir fonksiyonlar dizisine dönüştürür. f(a, b) f(a)(b) olur.

function curry(fn) {   return function(a) {     return function(b) {       return fn(a, b);     };   }; } function add(a, b) {   return a + b; } const curriedAdd = curry(add); const add5 = curriedAdd(5); console.log(add5(3)); // 8 console.log(curriedAdd(10)(20)); // 30

Nesneyi Derin Kopyala

Bir JavaScript nesnesinin derin kopyasını gerçekleştiren bir fonksiyon yazın.

Açıklama: Sığ kopya yalnızca üst düzey özellikleri kopyalar. Derin kopya, iç içe nesneler ve diziler de dahil olmak üzere tüm özellikleri özyinelemeli olarak kopyalar. Basit bir yol (sınırlamalarla, örneğin fonksiyonları, tarihleri, düzenli ifadeleri iyi işlemez) JSON.parse(JSON.stringify(obj)) kullanmaktır. Özyinelemeli bir yaklaşım daha sağlamdır.

function deepClone(obj) {   // Basit sürüm (sınırlamalarla)   try {       return JSON.parse(JSON.stringify(obj));   } catch (e) {       console.error("Kopyalama başarısız:", e);       return null;   }     // Daha sağlam özyinelemeli (temel örnek):   /*   if (obj === null || typeof obj !== 'object') {       return obj;   }   let clone = Array.isArray(obj) ? [] : {};   for (let key in obj) {       if (Object.prototype.hasOwnProperty.call(obj, key)) {           clone[key] = deepClone(obj[key]);       }   }   return clone;   */ } const original = { a: 1, b: { c: 2 } }; const cloned = deepClone(original); cloned.b.c = 3; console.log(original.b.c); // 2 (derin kopya olduğunu kanıtlar) console.log(cloned.b.c); // 3

Nesne Anahtarlarını Al

Bir nesneden anahtarların bir dizisini nasıl alırsınız?

Açıklama: Object.keys(obj) kullanın.

function getKeys(obj) {   return Object.keys(obj); } console.log(getKeys({a: 1, b: 2})); // ['a', 'b']

Nesne Değerlerini Al

Bir nesneden değerlerin bir dizisini nasıl alırsınız?

Açıklama: Object.values(obj) kullanın.

function getValues(obj) {   return Object.values(obj); } console.log(getValues({a: 1, b: 2})); // [1, 2]

Dizi Değeri İçeriyor mu Kontrol Et

Bir dizinin belirli bir değeri içerip içermediğini nasıl kontrol edersiniz?

Açıklama: Array.prototype.includes(value) kullanın.

function checkIncludes(arr, val) {   return arr.includes(val); } console.log(checkIncludes([1, 2, 3], 2)); // true

İki Diziyi Birleştir

İki diziyi tek bir dizide nasıl birleştirirsiniz?

Açıklama: Yayılma sözdizimi (...) veya Array.prototype.concat() kullanın.

function mergeArrays(arr1, arr2) {   return [...arr1, ...arr2]; } console.log(mergeArrays([1, 2], [3, 4])); // [1, 2, 3, 4]

Global Kapsamda 'this'i Açıkla

Bir tarayıcıda global kapsamda this neyi ifade eder?

Açıklama: Global yürütme bağlamında (herhangi bir fonksiyonun dışında), this global nesneyi ifade eder, bu da web tarayıcılarında window'dur.

console.log(this === window); // true (tarayıcı ortamında)

Bir Nesne Metodunda 'this'i Açıkla

Bir nesne metodunun içinde kullanıldığında this neyi ifade eder?

Açıklama: Bir fonksiyon bir nesnenin metodu olarak çağrıldığında, this metodun çağrıldığı nesneyi ifade eder.

const myObject = {   prop: 'Merhaba',   greet() {     return this.prop;   } }; console.log(myObject.greet()); // 'Merhaba'

Ok Fonksiyonlarıyla 'this'i Açıkla

Ok fonksiyonları this'i nasıl ele alır?

Açıklama: Ok fonksiyonlarının kendi this bağlamı yoktur. Bunun yerine, tanımlandıkları çevreleyen (sözcüksel) kapsamdan this'i miras alırlar.

function MyClass() {   this.value = 42;   setTimeout(() => {     console.log(this.value); // 42'yi loglar çünkü 'this' miras alınır   }, 100); } new MyClass();

`let`, `const` ve `var` Arasındaki Farklar

let, const ve var arasındaki temel farklar nelerdir?

Açıklama: var fonksiyon kapsamlıdır ve hoisted'dır. let ve const blok kapsamlıdır ve hoisted'dır ancak bildirilene kadar 'geçici ölü bölgede'dirler. const başlatılmalı ve yeniden atanamaz.

function scopeTest() {   var a = 1;   let b = 2;   const c = 3;   if (true) {     var a = 10; // Dıştaki 'a'yı yeniden bildirir ve etkiler     let b = 20; // Blok içinde yeni 'b'     // const c = 30; // Yeni bir 'c' olurdu     console.log(a, b, c); // 10, 20, 3   }   console.log(a, b, c); // 10, 2, 3 } scopeTest();

Promise Nedir?

JavaScript'te Promise'in ne olduğunu açıklayın.

Açıklama: Promise, asenkron bir işlemin nihai tamamlanmasını (veya başarısızlığını) ve ortaya çıkan değerini temsil eden bir nesnedir. Üç durumdan birinde olabilir: beklemede, yerine getirilmiş veya reddedilmiş.

const myPromise = new Promise((resolve, reject) => {   setTimeout(() => {     resolve('Başarılı!');     // reject('Hata!');   }, 1000); }); myPromise   .then(result => console.log(result))   .catch(error => console.error(error));

`async/await` Kullanımı

async ve await Promise'lerle çalışmayı nasıl basitleştirir?

Açıklama: async/await, Promise'ler üzerinde sentaktik şeker sağlar, asenkron kodu senkron koda biraz daha benzetir ve öyle davranmasını sağlar. Bir async fonksiyon her zaman bir Promise döndürür ve await bir Promise çözülene kadar yürütmeyi duraklatır.

function delay(ms) {   return new Promise(resolve => setTimeout(resolve, ms)); } async function run() {   console.log('Başlıyor...');   await delay(1000);   console.log('1 saniye bekledi.');   await delay(500);   console.log('Bir 0.5 saniye daha bekledi.');   return 'Bitti!'; } run().then(console.log);

Dizeyi Sayıya Dönüştür

Bir dizeyi sayıya nasıl dönüştürürsünüz?

Açıklama: parseInt(), parseFloat() veya birli artı operatörünü (+) kullanın.

const str = '123.45'; console.log(parseInt(str)); // 123 console.log(parseFloat(str)); // 123.45 console.log(+str); // 123.45

Sayıyı Dizeye Dönüştür

Bir sayıyı dizeye nasıl dönüştürürsünüz?

Açıklama: String(), number.toString() veya dize birleştirmeyi kullanın.

const num = 123; console.log(String(num)); // '123' console.log(num.toString()); // '123' console.log('' + num); // '123'

`JSON.stringify` Nedir?

JSON.stringify ne yapar?

Açıklama: Bir JavaScript nesnesini veya değerini bir JSON dizesine dönüştürür.

const obj = { name: 'Alice', age: 30 }; const jsonString = JSON.stringify(obj); console.log(jsonString); // '{"name":"Alice","age":30}'

`JSON.parse` Nedir?

JSON.parse ne yapar?

Açıklama: Bir JSON dizesini ayrıştırır, dize tarafından açıklanan JavaScript değerini veya nesnesini oluşturur.

const jsonString = '{"name":"Alice","age":30}'; const obj = JSON.parse(jsonString); console.log(obj.name); // 'Alice'

Dizilerde Yayılma Operatörü

Yayılma operatörü dizilerle nasıl kullanılır?

Açıklama: Bir yinelenebilirin (dizi gibi) sıfır veya daha fazla argümanın veya öğenin beklendiği yerlerde genişletilmesini sağlar. Kopyalama, birleştirme ve öğe ekleme için kullanışlıdır.

const arr1 = [1, 2]; const arr2 = [3, 4]; const combined = [...arr1, ...arr2]; // [1, 2, 3, 4] const copy = [...arr1]; // [1, 2]

Nesnelerde Yayılma Operatörü

Yayılma operatörü nesnelerle nasıl kullanılır?

Açıklama: Nesne özelliklerinin kopyalanmasını ve birleştirilmesini sağlar.

const obj1 = { a: 1, b: 2 }; const obj2 = { b: 3, c: 4 }; const merged = { ...obj1, ...obj2 }; // { a: 1, b: 3, c: 4 } const copy = { ...obj1 }; // { a: 1, b: 2 }

Dizileri Yapı Bozma

Bir örnekle dizi yapı bozmayı açıklayın.

Açıklama: Dizilerden değerleri ayrı değişkenlere açmayı mümkün kılan bir sözdizimidir.

const [a, b] = [10, 20]; console.log(a); // 10 console.log(b); // 20 const [x, , z] = [1, 2, 3]; console.log(z); // 3

Nesneleri Yapı Bozma

Bir örnekle nesne yapı bozmayı açıklayın.

Açıklama: Nesnelerden özellikleri ayrı değişkenlere açmayı mümkün kılar.

const person = { name: 'Bob', age: 25 }; const { name, age } = person; console.log(name); // 'Bob' console.log(age); // 25 const { name: personName } = person; console.log(personName); // 'Bob'

`call` Uygula

Function.prototype.call'ın temel bir sürümünü nasıl uygulayabilirsiniz?

Açıklama: call, belirtilen bir this değeri ve ayrı ayrı sağlanan argümanlarla bir fonksiyonu çağırır. Fonksiyonu this bağlamına ekleyebilir, çağırabilir ve sonra kaldırabilirsiniz.

Function.prototype.myCall = function(context, ...args) {   context = context || window;   const uniqueId = Symbol(); // Benzersiz bir anahtar kullanın   context[uniqueId] = this;   const result = context[uniqueId](...args);   delete context[uniqueId];   return result; } function greet(greeting, punctuation) {   console.log(`${greeting}, ${this.name}${punctuation}`); } greet.myCall({ name: 'Charlie' }, 'Selam', '!'); // Selam, Charlie!

`apply` Uygula

Function.prototype.apply'ın temel bir sürümünü nasıl uygulayabilirsiniz?

Açıklama: apply, call'a benzer, ancak argümanları bir dizi olarak kabul eder.

Function.prototype.myApply = function(context, argsArray) {   context = context || window;   const uniqueId = Symbol();   context[uniqueId] = this;   const result = context[uniqueId](...(argsArray || []));   delete context[uniqueId];   return result; } function greet(greeting, punctuation) {   console.log(`${greeting}, ${this.name}${punctuation}`); } greet.myApply({ name: 'David' }, ['Merhaba', '.']); // Merhaba, David.

Olay Döngüsünü Açıklayın

JavaScript Olay Döngüsünü kısaca açıklayın.

Açıklama: JavaScript tek iş parçacıklı bir dildir ancak olay döngüsü kullanarak eşzamanlılık sağlar. Çağrı yığını senkron kodu işler. Web API'leri (setTimeout, fetch gibi) asenkron işlemleri yönetir. Asenkron bir işlem bittiğinde, geri çağırımı geri çağırım kuyruğuna (veya Promise'ler için mikro görev kuyruğuna) gider. Olay döngüsü, çağrı yığınının boş olup olmadığını sürekli kontrol eder; eğer boşsa, bir sonraki geri çağırımı yürütmek üzere kuyruktan yığına taşır.

console.log('Start'); setTimeout(() => { console.log('Timeout Callback'); // Geri Çağırım Kuyruğuna gider }, 0); Promise.resolve().then(() => { console.log('Promise Resolved'); // Mikro Görev Kuyruğuna gider }); console.log('End'); // Çıktı Sırası: Start, End, Promise Resolved, Timeout Callback // (Mikro görevler Makro görevlerden/Geri Çağırımlardan önce çalışır)

İkili Arama

Sıralı bir dizi için ikili arama fonksiyonunu uygulayın.

Açıklama: İkili arama, arama aralığını sürekli ikiye bölerek sıralı bir dizideki bir öğeyi verimli bir şekilde bulur. Eğer arama anahtarının değeri aralığın ortasındaki öğeden küçükse, aralığı alt yarıya daraltın. Aksi takdirde, üst yarıya daraltın. Bu işlemi değer bulunana veya aralık boşalana kadar yaparsınız.

function binarySearch(sortedArray, key) { let start = 0; let end = sortedArray.length - 1; while (start <= end) { let middle = Math.floor((start + end) / 2); if (sortedArray[middle] === key) { return middle; // Bulundu } else if (sortedArray[middle] < key) { start = middle + 1; // Sağ yarıyı ara } else { end = middle - 1; // Sol yarıyı ara } } return -1; // Bulunamadı } console.log(binarySearch([1, 3, 5, 7, 9, 11], 7)); // 3 console.log(binarySearch([1, 3, 5, 7, 9, 11], 2)); // -1

Birleştirme Sıralaması

Birleştirme Sıralaması algoritmasını uygulayın.

Açıklama: Birleştirme Sıralaması, böl ve yönet algoritmasıdır. Giriş dizisini iki yarıya böler, iki yarı için kendini çağırır ve ardından iki sıralanmış yarıyı birleştirir. Birleştirme fonksiyonu çok önemlidir; iki sıralanmış alt diziyi tek bir sıralanmış diziye birleştirir.

function mergeSort(arr) { if (arr.length <= 1) return arr; const mid = Math.floor(arr.length / 2); const left = mergeSort(arr.slice(0, mid)); const right = mergeSort(arr.slice(mid)); return merge(left, right); } function merge(left, right) { let result = []; let leftIndex = 0; let rightIndex = 0; while (leftIndex < left.length && rightIndex < right.length) { if (left[leftIndex] < right[rightIndex]) { result.push(left[leftIndex]); leftIndex++; } else { result.push(right[rightIndex]); rightIndex++; } } return result.concat(left.slice(leftIndex)).concat(right.slice(rightIndex)); } console.log(mergeSort([38, 27, 43, 3, 9, 82, 10])); // [3, 9, 10, 27, 38, 43, 82]

Hızlı Sıralama

Hızlı Sıralama algoritmasını uygulayın.

Açıklama: Hızlı Sıralama da bir böl ve yönet algoritmasıdır. Bir öğeyi pivot olarak seçer ve verilen diziyi seçilen pivot etrafında böler. Pivottan küçük öğeler sola, daha büyük öğeler sağa gider. Daha sonra alt dizileri özyinelemeli olarak sıralar.

function quickSort(arr) { if (arr.length <= 1) return arr; const pivot = arr[arr.length - 1]; const left = []; const right = []; for (let i = 0; i < arr.length - 1; i++) { if (arr[i] < pivot) { left.push(arr[i]); } else { right.push(arr[i]); } } return [...quickSort(left), pivot, ...quickSort(right)]; } console.log(quickSort([10, 8, 2, 1, 6, 3, 9, 4, 7, 5])); // [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]

Kabarcık Sıralaması

Kabarcık Sıralaması algoritmasını uygulayın.

Açıklama: Kabarcık Sıralaması, liste boyunca art arda adım atan, bitişik öğeleri karşılaştıran ve yanlış sıradaysa yerlerini değiştiren basit bir sıralama algoritmasıdır. Liste sıralanana kadar liste boyunca geçiş tekrarlanır.

function bubbleSort(arr) { let n = arr.length; let swapped; do { swapped = false; for (let i = 0; i < n - 1; i++) { if (arr[i] > arr[i + 1]) { [arr[i], arr[i + 1]] = [arr[i + 1], arr[i]]; // Yer değiştirme swapped = true; } } n--; // Optimizasyon: son öğe zaten yerindedir } while (swapped); return arr; } console.log(bubbleSort([64, 34, 25, 12, 22, 11, 90])); // [11, 12, 22, 25, 34, 64, 90]

Tekrarlayan Karakterler Olmadan En Uzun Alt Dizi

Verilen bir dizgedeki tekrarlayan karakterler olmadan en uzun alt dizinin uzunluğunu bulun.

Açıklama: Kayar pencere tekniğini kullanın. Bir pencere (alt dizi) ve o penceredeki karakterlerden oluşan bir küme tutun. Sağ işaretçiyi hareket ettirerek pencereyi genişletin. Tekrarlayan bir karakter bulunursa, tekrarlayan karakter kaldırılana kadar pencereyi soldan küçültün.

function lengthOfLongestSubstring(s) { let maxLength = 0; let start = 0; const charMap = {}; for (let end = 0; end < s.length; end++) { const char = s[end]; if (charMap[char] >= start) { start = charMap[char] + 1; } charMap[char] = end; maxLength = Math.max(maxLength, end - start + 1); } return maxLength; } console.log(lengthOfLongestSubstring('abcabcbb')); // 3 ('abc') console.log(lengthOfLongestSubstring('bbbbb')); // 1 ('b') console.log(lengthOfLongestSubstring('pwwkew')); // 3 ('wke')

Bağlı Liste Uygulaması

Add ve print metotlarına sahip tek yönlü bir bağlı liste uygulayın.

Açıklama: Bağlı liste, öğelerin bitişik bellek konumlarında depolanmadığı doğrusal bir veri yapısıdır. Her öğe (düğüm) bir sonrakini işaret eder. Baş düğümü ve yeni düğümleri yönetmek için bir Node sınıfına ve bir LinkedList sınıfına ihtiyacınız var.

class Node { constructor(data, next = null) { this.data = data; this.next = next; } } class LinkedList { constructor() { this.head = null; } add(data) { const newNode = new Node(data); if (!this.head) { this.head = newNode; } else { let current = this.head; while (current.next) { current = current.next; } current.next = newNode; } } print() { let current = this.head; let list = ''; while (current) { list += current.data + ' -> '; current = current.next; } console.log(list + 'null'); } } const list = new LinkedList(); list.add(10); list.add(20); list.add(30); list.print(); // 10 -> 20 -> 30 -> null

İkili Arama Ağacı (BST) Uygulaması

Ekle ve bul metotlarına sahip bir İkili Arama Ağacı uygulayın.

Açıklama: BST, aşağıdaki özelliklere sahip düğüm tabanlı bir ikili ağaç veri yapısıdır: Bir düğümün sol alt ağacı yalnızca düğümün anahtarından küçük anahtarlara sahip düğümleri içerir. Bir düğümün sağ alt ağacı yalnızca düğümün anahtarından büyük anahtarlara sahip düğümleri içerir. Her iki alt ağaç da ikili arama ağacı olmalıdır.

class Node { constructor(data) { this.data = data; this.left = null; this.right = null; } } class BST { constructor() { this.root = null; } insert(data) { const newNode = new Node(data); if (!this.root) { this.root = newNode; return; } this._insertNode(this.root, newNode); } _insertNode(node, newNode) { if (newNode.data < node.data) { if (!node.left) node.left = newNode; else this._insertNode(node.left, newNode); } else { if (!node.right) node.right = newNode; else this._insertNode(node.right, newNode); } } find(data) { return this._findNode(this.root, data); } _findNode(node, data) { if (!node) return null; if (data < node.data) return this._findNode(node.left, data); else if (data > node.data) return this._findNode(node.right, data); else return node; } } const bst = new BST(); bst.insert(10); bst.insert(5); bst.insert(15); bst.insert(7); console.log(bst.find(7)); // Node { data: 7, left: null, right: null } console.log(bst.find(12)); // null

Bir Diziyi Döndürme

Bir diziyi k adım sağa döndüren bir fonksiyon yazın.

Açıklama: Bir diziyi döndürmek, öğelerini hareket ettirmek anlamına gelir. Sağ döndürme için son öğe ilk öğe olur. Bunu k kez tekrarlamak işe yarar ancak verimsizdir. Daha iyi bir yol, dizi manipülasyonu kullanmak veya yeni konumları hesaplamaktır.

function rotateArray(nums, k) { k = k % nums.length; // k > uzunluk olduğu durumları ele alın if (k === 0) return nums; const partToMove = nums.splice(nums.length - k); nums.unshift(...partToMove); return nums; } console.log(rotateArray([1, 2, 3, 4, 5, 6, 7], 3)); // [5, 6, 7, 1, 2, 3, 4]

İki Dizinin Kesişimini Bulma

İki dizi verildiğinde, kesişimlerini (her ikisinde de ortak olan öğeler) hesaplamak için bir fonksiyon yazın.

Açıklama: İyi bir yaklaşım, O(1) ortalama zamanlı aramalar için bir diziyi bir Set'e dönüştürmektir. Ardından, ikinci dizi boyunca yineleyin ve her öğenin kümede olup olmadığını kontrol edin. Eşleşmeleri toplayın.

function intersection(nums1, nums2) { const set1 = new Set(nums1); const resultSet = new Set(); for (const num of nums2) { if (set1.has(num)) { resultSet.add(num); } } return [...resultSet]; } console.log(intersection([1, 2, 2, 1], [2, 2])); // [2] console.log(intersection([4, 9, 5], [9, 4, 9, 8, 4])); // [9, 4]

Anagramları Grupla

Bir dizge dizisi verildiğinde, anagramları bir araya getirin.

Açıklama: Anahtar, her anagram grubu için benzersiz bir imza bulmaktır. Yaygın bir yol, her kelimeyi alfabetik olarak sıralamaktır. Aynı sıralanmış dizgeyle sonuçlanan kelimeler anagramlardır. Anahtarların sıralanmış kelimeler ve değerlerin orijinal kelime dizileri olduğu bir hash haritası kullanın.

function groupAnagrams(strs) { const map = {}; for (const str of strs) { const sortedStr = str.split('').sort().join(''); if (!map[sortedStr]) { map[sortedStr] = []; } map[sortedStr].push(str); } return Object.values(map); } console.log(groupAnagrams(['eat', 'tea', 'tan', 'ate', 'nat', 'bat'])); // Çıktı: [['eat', 'tea', 'ate'], ['tan', 'nat'], ['bat']]

Sıfırları Sona Taşıma

Bir nums dizisi verildiğinde, sıfır olmayan öğelerin göreceli sırasını korurken tüm 0'ları sona taşıyan bir fonksiyon yazın.

Açıklama: Bir iki işaretçi veya kartopu yaklaşımı kullanın. Bir işaretçi, bir sonraki sıfır olmayan öğenin gitmesi gereken konumu takip eder. Dizi boyunca yineleyin; bir öğe sıfır değilse, onu işaretçinin konumuna yerleştirin ve işaretçiyi artırın. Son olarak, geri kalanını sıfırlarla doldurun.

function moveZeroes(nums) { let nonZeroIndex = 0; // Tüm sıfır olmayan öğeleri öne taşıyın for (let i = 0; i < nums.length; i++) { if (nums[i] !== 0) { nums[nonZeroIndex] = nums[i]; nonZeroIndex++; } } // Geri kalanını sıfırlarla doldurun for (let i = nonZeroIndex; i < nums.length; i++) { nums[i] = 0; } return nums; } console.log(moveZeroes([0, 1, 0, 3, 12])); // [1, 3, 12, 0, 0]

Maksimum Alt Dizi (Kadane Algoritması)

Bir tamsayı dizisi nums verildiğinde, en büyük toplama sahip bitişik alt diziyi (en az bir sayı içeren) bulun ve toplamını döndürün.

Açıklama: Kadane algoritması, bunu çözmek için verimli bir yoldur. Dizi boyunca yineleyin, mevcut konumda sona eren currentMax toplamını ve şimdiye kadar bulunan globalMax toplamını takip edin. Eğer currentMax negatif olursa, onu 0'a (veya daha doğrusu, mevcut öğeye) sıfırlayın.

function maxSubArray(nums) { let globalMax = -Infinity; let currentMax = 0; for (let i = 0; i < nums.length; i++) { currentMax = Math.max(nums[i], currentMax + nums[i]); if (currentMax > globalMax) { globalMax = currentMax; } } return globalMax; } console.log(maxSubArray([-2, 1, -3, 4, -1, 2, 1, -5, 4])); // 6 ([4, -1, 2, 1]'den)

Bir Dizgenin Permütasyonları

Verilen bir dizgenin tüm permütasyonlarını oluşturan bir fonksiyon yazın.

Açıklama: Bu genellikle özyineleme ve geri izleme kullanılarak çözülür. Her karakter için, onu sabitleyin ve dizgenin geri kalanı için permütasyonları özyinelemeli olarak oluşturun. Temel durum: dizge yalnızca bir karaktere sahip olduğunda, onu döndürün.

function stringPermutations(str) { if (str.length === 0) return ['']; if (str.length === 1) return [str]; const results = []; for (let i = 0; i < str.length; i++) { const char = str[i]; const remainingChars = str.slice(0, i) + str.slice(i + 1); const perms = stringPermutations(remainingChars); for (const perm of perms) { results.push(char + perm); } } return [...new Set(results)]; // Gerekirse yinelenen karakterleri ele almak için Set kullanın } console.log(stringPermutations('abc')); // ['abc', 'acb', 'bac', 'bca', 'cab', 'cba'] console.log(stringPermutations('aab')); // ['aab', 'aba', 'baa']

En Büyük Ortak Bölen (EBOB)

İki sayının En Büyük Ortak Böleni'ni (EBOB) bulan bir fonksiyon yazın.

Açıklama: Öklid algoritması verimli bir yöntemdir. Eğer b 0 ise, a EBOB'dur. Aksi takdirde, a ve b'nin EBOB'u, b ve a % b'nin (a'nın b'ye bölümünden kalan) EBOB'u ile aynıdır.

function gcd(a, b) { while (b !== 0) { let temp = b; b = a % b; a = temp; } return a; } console.log(gcd(48, 18)); // 6 console.log(gcd(101, 103)); // 1

En Küçük Ortak Kat (EKOK)

İki sayının En Küçük Ortak Katını (EKOK) bulan bir fonksiyon yazın.

Açıklama: EKOK, EBOB kullanılarak şu formülle hesaplanabilir: EKOK(a, b) = |a * b| / EBOB(a, b).

function gcd(a, b) { // Önceki problemden yardımcı fonksiyon while (b !== 0) { let temp = b; b = a % b; a = temp; } return a; } function lcm(a, b) { if (a === 0 || b === 0) return 0; return Math.abs(a * b) / gcd(a, b); } console.log(lcm(15, 20)); // 60 console.log(lcm(7, 5)); // 35

Promise.all Uygulaması

Promise.all gibi davranan bir fonksiyon uygulayın.

Açıklama: Promise.all, bir dizi söz verir ve tüm giriş sözleri çözüldüğünde çözülen veya herhangi bir giriş sözü reddedilirse reddedilen tek bir söz döndürür. Çözülen değer, çözülen değerlerin bir dizisidir.

function myPromiseAll(promises) { return new Promise((resolve, reject) => { const results = []; let completedCount = 0; const numPromises = promises.length; if (numPromises === 0) { resolve([]); return; } promises.forEach((promise, index) => { Promise.resolve(promise) .then(value => { results[index] = value; completedCount++; if (completedCount === numPromises) { resolve(results); } }) .catch(reject); // Herhangi bir hatada hemen reddedin }); }); } // Örnek kullanım: const p1 = Promise.resolve(3); const p2 = 42; const p3 = new Promise((resolve) => setTimeout(resolve, 100, 'foo')); myPromiseAll([p1, p2, p3]).then(values => console.log(values)); // [3, 42, 'foo']

İkili Ağacı Tersine Çevirme

Bir ikili ağacı tersine çeviren bir fonksiyon yazın.

Açıklama: Bir ikili ağacı tersine çevirmek için, her düğüm için sol ve sağ çocukları değiştirirsiniz. Bu özyinelemeli veya yinelemeli olarak (bir kuyruk veya yığın kullanarak) yapılabilir.

class Node { constructor(val, left = null, right = null) { this.val = val; this.left = left; this.right = right; } } function invertTree(root) { if (root === null) { return null; } // Çocukları değiştirin [root.left, root.right] = [root.right, root.left]; // Sol ve sağ çocuklar için özyinelemeli çağrı yapın invertTree(root.left); invertTree(root.right); return root; } // Örnek: 4 -> [2, 7] -> [1, 3, 6, 9] // Olur: 4 -> [7, 2] -> [9, 6, 3, 1]

İkili Ağacın Maksimum Derinliği

Bir ikili ağaç verildiğinde, maksimum derinliğini bulun.

Açıklama: Maksimum derinlik, kök düğümden en uzak yaprak düğüme kadar olan en uzun yoldaki düğüm sayısıdır. Bu özyinelemeli olarak bulunabilir: MaxDerinlik = 1 + max(MaxDerinlik(sol), MaxDerinlik(sağ)). Temel durum, bir düğümün boş olmasıdır, derinliği 0'dır.

class Node { constructor(val, left = null, right = null) { this.val = val; this.left = left; this.right = right; } } function maxDepth(root) { if (root === null) { return 0; } const leftDepth = maxDepth(root.left); const rightDepth = maxDepth(root.right); return Math.max(leftDepth, rightDepth) + 1; } // Örnek: 3 -> [9, 20] -> [null, null, 15, 7] const tree = new Node(3, new Node(9), new Node(20, new Node(15), new Node(7))); console.log(maxDepth(tree)); // 3

Hisse Senedi Alış/Satış için En İyi Zaman

prices dizisi verildiğinde, prices[i] i. gündeki belirli bir hisse senedinin fiyatıdır. Bir hisse senedi almak için tek bir gün seçerek ve o hisse senedini gelecekte farklı bir günde satarak karınızı en üst düzeye çıkarmak istersiniz. Maksimum karı döndürün.

Açıklama: Fiyatlar boyunca yineleyin, şimdiye kadar karşılaşılan minimum fiyatı (minPrice) ve şimdiye kadar bulunan maksimum karı (maxProfit) takip edin. Her gün için, bugün satmanız durumunda potansiyel karı (mevcut fiyat - minPrice) hesaplayın ve daha yüksekse maxProfit'i güncelleyin.

function maxProfit(prices) { let minPrice = Infinity; let maxProfit = 0; for (let i = 0; i < prices.length; i++) { if (prices[i] < minPrice) { minPrice = prices[i]; } else if (prices[i] - minPrice > maxProfit) { maxProfit = prices[i] - minPrice; } } return maxProfit; } console.log(maxProfit([7, 1, 5, 3, 6, 4])); // 5 (1'den al, 6'dan sat) console.log(maxProfit([7, 6, 4, 3, 1])); // 0 (Kar mümkün değil)

Tek Sayı

Boş olmayan bir tamsayı dizisi nums verildiğinde, her eleman iki kez görünür, sadece biri hariç. Bu tek olanı bulun.

Açıklama: Bunu çözmek için çok verimli bir yol XOR bit düzeyinde operatörünü (^) kullanmaktır. Bir sayının kendisiyle XOR'lanması 0 ile sonuçlanır. Bir sayının 0 ile XOR'lanması sayının kendisiyle sonuçlanır. Dizideki tüm sayıları XOR'larsanız, çiftler birbirini götürecek (0 olacaktır), yalnızca tek sayı kalacaktır.

function singleNumber(nums) { let result = 0; for (const num of nums) { result ^= num; } return result; } console.log(singleNumber([2, 2, 1])); // 1 console.log(singleNumber([4, 1, 2, 1, 2])); // 4

Çoğunluk Elemanı

n boyutunda bir nums dizisi verildiğinde, çoğunluk elemanını döndürün. Çoğunluk elemanı, ⌊n / 2⌋'den fazla kez görünen elemandır.

Açıklama: Boyer-Moore Oylama Algoritması verimli bir yoldur. Bir aday ve bir sayım başlatın. Dizi boyunca yineleyin. Eğer sayım 0 ise, mevcut elemanı aday olarak ayarlayın. Eğer mevcut eleman adayla eşleşirse, sayımı artırın; aksi takdirde, sayımı azaltın.

function majorityElement(nums) { let candidate = null; let count = 0; for (const num of nums) { if (count === 0) { candidate = num; } count += (num === candidate) ? 1 : -1; } return candidate; } console.log(majorityElement([3, 2, 3])); // 3 console.log(majorityElement([2, 2, 1, 1, 1, 2, 2])); // 2

Merdiven Çıkma

Bir merdiven çıkıyorsunuz. Tepeye ulaşmak için n adım gerekir. Her seferinde 1 veya 2 adım tırmanabilirsiniz. Tepeye kaç farklı şekilde çıkabilirsiniz?

Açıklama: Bu klasik bir dinamik programlama problemidir, Fibonacci dizisine çok benzer. n adımına ulaşma yollarının sayısı, n-1 adımına ulaşma yollarının (1 adım atarak) ve n-2 adımına ulaşma yollarının (2 adım atarak) toplamıdır. dp[n] = dp[n-1] + dp[n-2].

function climbStairs(n) { if (n <= 2) return n; let oneStepBefore = 2; let twoStepsBefore = 1; let allWays = 0; for (let i = 3; i <= n; i++) { allWays = oneStepBefore + twoStepsBefore; twoStepsBefore = oneStepBefore; oneStepBefore = allWays; } return allWays; } console.log(climbStairs(2)); // 2 (1+1, 2) console.log(climbStairs(3)); // 3 (1+1+1, 1+2, 2+1) console.log(climbStairs(4)); // 5

Kendisi Hariç Dizinin Çarpımı

Bir tamsayı dizisi nums verildiğinde, answer[i]'nin nums[i] hariç nums'un tüm öğelerinin çarpımına eşit olduğu bir answer dizisi döndürün. Bölme operatörünü kullanmayın.

Açıklama: Bunu, önek çarpımlarını ve sonek çarpımlarını hesaplayarak çözebilirsiniz. i dizinindeki sonuç, i'den önceki tüm öğelerin çarpımının i'den sonraki tüm öğelerin çarpımıyla çarpılmasıdır.

function productExceptSelf(nums) { const n = nums.length; const answer = new Array(n).fill(1); // Önek çarpımlarını hesaplayın let prefix = 1; for (let i = 0; i < n; i++) { answer[i] = prefix; prefix *= nums[i]; } // Sonek çarpımlarını hesaplayın ve önekle çarpın let suffix = 1; for (let i = n - 1; i >= 0; i--) { answer[i] *= suffix; suffix *= nums[i]; } return answer; } console.log(productExceptSelf([1, 2, 3, 4])); // [24, 12, 8, 6]

Ada Sayısı

1'ler (kara) ve 0'lar (su) içeren 2 boyutlu bir ızgara haritası verildiğinde, ada sayısını sayın. Bir ada su ile çevrilidir ve bitişik karaların yatay veya dikey olarak bağlanmasıyla oluşur.

Açıklama: Izgaranın her hücresini yineleyin. Eğer bir '1' (kara) bulursanız, ada sayısını artırın ve o hücreden başlayarak bir Derinlik Öncelikli Arama (DFS) veya Genişlik Öncelikli Arama (BFS) başlatın. Arama sırasında, yeniden saymaktan kaçınmak için tüm bağlı '1'leri '0' (veya ziyaret edildi) olarak işaretleyin.

function numIslands(grid) { if (!grid || grid.length === 0) return 0; let count = 0; const rows = grid.length; const cols = grid[0].length; function dfs(r, c) { if (r < 0 || c < 0 || r >= rows || c >= cols || grid[r][c] === '0') { return; } grid[r][c] = '0'; // Ziyaret edildi olarak işaretle dfs(r + 1, c); dfs(r - 1, c); dfs(r, c + 1); dfs(r, c - 1); } for (let r = 0; r < rows; r++) { for (let c = 0; c < cols; c++) { if (grid[r][c] === '1') { count++; dfs(r, c); } } } return count; } const grid1 = [ ['1', '1', '1', '1', '0'], ['1', '1', '0', '1', '0'], ['1', '1', '0', '0', '0'], ['0', '0', '0', '0', '0'] ]; // console.log(numIslands(grid1)); // 1 (Kopyasında çalıştırmak veya ızgarayı geri yüklemek gerekir)

LRU Önbellek

En Son Kullanılan (LRU) Önbelleği için bir veri yapısı tasarlayın ve uygulayın. Get ve Put işlemlerini desteklemelidir.

Açıklama: Bir LRU önbelleği, kapasiteye ulaşıldığında en az kullanılan öğeyi çıkarır. Yaygın bir uygulama, O(1) arama için bir Map (veya bir hash haritası) ve yakın zamanda kullanılan durumun O(1) güncellemeleri için Çift Yönlü Bağlı Liste kullanır. JavaScript'in Map'i ekleme sırasını korur, bu da temel bir uygulamayı basitleştirebilir.

class LRUCache { constructor(capacity) { this.capacity = capacity; this.cache = new Map(); } get(key) { if (!this.cache.has(key)) return -1; const value = this.cache.get(key); this.cache.delete(key); // En son kullanılan'a yeniden eklemek için kaldırın this.cache.set(key, value); return value; } put(key, value) { if (this.cache.has(key)) { this.cache.delete(key); } else if (this.cache.size >= this.capacity) { const oldestKey = this.cache.keys().next().value; this.cache.delete(oldestKey); } this.cache.set(key, value); } } const cache = new LRUCache(2); cache.put(1, 1); cache.put(2, 2); console.log(cache.get(1)); // 1 cache.put(3, 3); // 2'yi çıkarır console.log(cache.get(2)); // -1

Parantez Oluşturma

n çift parantez verildiğinde, iyi biçimlendirilmiş parantezlerin tüm kombinasyonlarını oluşturan bir fonksiyon yazın.

Açıklama: Bu klasik bir geri izleme problemidir. Açık ve kapalı parantezler için sayıları tutun. Açık parantez sayım < n ise bir açık parantez ekleyebilirsiniz. Kapalı parantez sayım < açık parantez sayım ise bir kapalı parantez ekleyebilirsiniz. Temel durum, dizge uzunluğunun 2 * n'ye ulaşmasıdır.

function generateParenthesis(n) { const results = []; function backtrack(currentString, openCount, closeCount) { if (currentString.length === n * 2) { results.push(currentString); return; } if (openCount < n) { backtrack(currentString + '(', openCount + 1, closeCount); } if (closeCount < openCount) { backtrack(currentString + ')', openCount, closeCount + 1); } } backtrack('', 0, 0); return results; } console.log(generateParenthesis(3)); // ['((()))', '(()())', '(())()', '()(())', '()()()']

En Çok Su İçeren Konteyner

n adet negatif olmayan tamsayı a1, a2, ..., an verildiğinde, her biri (i, ai) koordinatındaki bir noktayı temsil eder. Line i'nin iki uç noktası (i, ai) ve (i, 0) olacak şekilde n dikey çizgi çizilir. Birlikte x ekseniyle bir kap oluşturan iki çizgi bulun, öyle ki kap en çok su içersin.

Açıklama: İki işaretçi yaklaşımını kullanın. Bir işaretçi başlangıçta, diğeri sonda olacak şekilde başlayın. Alanı hesaplayın. Alan kısa çizgi ile sınırlıdır. Potansiyel olarak daha büyük bir alan bulmak için, kısa çizgiyi gösteren işaretçiyi içeri doğru hareket ettirin.

function maxArea(height) { let max = 0; let left = 0; let right = height.length - 1; while (left < right) { const h = Math.min(height[left], height[right]); const w = right - left; max = Math.max(max, h * w); if (height[left] < height[right]) { left++; } else { right--; } } return max; } console.log(maxArea([1, 8, 6, 2, 5, 4, 8, 3, 7])); // 49

3 Sayı Toplamı

n tamsayı içeren bir nums dizisi verildiğinde, nums içinde a + b + c = 0 olacak şekilde a, b, c elemanları var mı? Toplamı sıfır olan tüm benzersiz üçlüleri bulun.

Açıklama: İlk olarak, diziyi sıralayın. Ardından, bir i işaretçisiyle dizi boyunca yineleyin. Her i için, -nums[i]'ye kadar toplayan iki sayı bulmak için iki işaretçi daha, sol (i+1'den başlayarak) ve sağ (sondan başlayarak) kullanın. Benzersiz üçlüler sağlamak için tekrarlayanları ele alın.

function threeSum(nums) { nums.sort((a, b) => a - b); const results = []; for (let i = 0; i < nums.length - 2; i++) { if (i > 0 && nums[i] === nums[i - 1]) continue; // i için tekrarlayanları atla let left = i + 1; let right = nums.length - 1; let target = -nums[i]; while (left < right) { let sum = nums[left] + nums[right]; if (sum === target) { results.push([nums[i], nums[left], nums[right]]); while (left < right && nums[left] === nums[left + 1]) left++; // Tekrarlayanları atla while (left < right && nums[right] === nums[right - 1]) right--; // Tekrarlayanları atla left++; right--; } else if (sum < target) { left++; } else { right--; } } } return results; } console.log(threeSum([-1, 0, 1, 2, -1, -4])); // [[-1, -1, 2], [-1, 0, 1]]

Arama Ekleme Konumu

Belirgin tamsayılardan oluşan sıralı bir dizi ve bir hedef değer verildiğinde, hedef bulunursa dizini döndürün. Bulunmazsa, sırayla eklenirse olması gereken dizini döndürün.

Açıklama: Bu, ikili aramanın bir varyasyonudur. İkili arama yapın, ancak öğe bulunamazsa, başlangıç işaretçisi öğenin eklenmesi gereken konumda bitecektir.

function searchInsert(nums, target) { let start = 0; let end = nums.length - 1; while (start <= end) { let mid = Math.floor((start + end) / 2); if (nums[mid] === target) { return mid; } else if (nums[mid] < target) { start = mid + 1; } else { end = mid - 1; } } return start; // Bulunmazsa, başlangıç ​​ekleme noktasıdır } console.log(searchInsert([1, 3, 5, 6], 5)); // 2 console.log(searchInsert([1, 3, 5, 6], 2)); // 1 console.log(searchInsert([1, 3, 5, 6], 7)); // 4

İki Sıralı Listeyi Birleştirme (Bağlı Listeler)

Sıralı iki bağlı listeyi birleştirin ve yeni bir sıralı liste olarak döndürün. Yeni liste, ilk iki listenin düğümlerini birleştirerek oluşturulmalıdır.

Açıklama: Süreci basitleştirmek için kukla bir baş düğümü kullanın. Yeni listeyi oluşturmak için bir işaretçi kullanın. Her iki giriş listesinin mevcut düğümlerini karşılaştırın ve küçük olanı yeni listeye ekleyin, o listenin işaretçisini ilerletin. Bir liste tükenene kadar tekrarlayın, ardından diğer listenin geri kalanını ekleyin.

class ListNode { constructor(val = 0, next = null) { this.val = val; this.next = next; } } function mergeTwoLists(l1, l2) { let dummyHead = new ListNode(); let current = dummyHead; while (l1 !== null && l2 !== null) { if (l1.val < l2.val) { current.next = l1; l1 = l1.next; } else { current.next = l2; l2 = l2.next; } current = current.next; } current.next = l1 !== null ? l1 : l2; return dummyHead.next; } // Örnek: 1->2->4 ve 1->3->4 => 1->1->2->3->4->4

Simetrik Ağaç

İkili bir ağaç verildiğinde, kendisinin bir aynası olup olmadığını (yani merkezine göre simetrik olup olmadığını) kontrol edin.

Açıklama: Bu özyinelemeli olarak çözülebilir. Bir ağaç, sol alt ağacın sağ alt ağacın ayna görüntüsü olması durumunda simetriktir. İki ağacın ayna olup olmadığını kontrol eden bir isMirror(t1, t2) yardımcı fonksiyonu oluşturun. Bu fonksiyon şunları doğrulamalıdır: 1. t1.val === t2.val. 2. t1.left, t2.right'ın aynasıdır. 3. t1.right, t2.left'in aynasıdır.

class Node { constructor(val, left = null, right = null) { this.val = val; this.left = left; this.right = right; } } function isSymmetric(root) { if (!root) return true; function isMirror(t1, t2) { if (!t1 && !t2) return true; if (!t1 || !t2 || t1.val !== t2.val) return false; return isMirror(t1.left, t2.right) && isMirror(t1.right, t2.left); } return isMirror(root.left, root.right); } // Örnek: 1 -> [2, 2] -> [3, 4, 4, 3] simetriktir.

Seviye Sırasına Göre Geçiş (BST/Ağaç)

İkili bir ağaç verildiğinde, düğüm değerlerinin seviye sırasına göre geçişini döndürün. (yani, soldan sağa, seviye seviye).

Açıklama: Bu bir Genişlik Öncelikli Aramadır (BFS). Bir kuyruk kullanın. Kökü kuyruğa ekleyerek başlayın. Kuyruk boş değilken, mevcut seviyedeki tüm düğümleri işleyin. İşlenen her düğüm için, çocuklarını (eğer varsa) bir sonraki seviye için kuyruğa ekleyin.

class Node { constructor(val, left = null, right = null) { this.val = val; this.left = left; this.right = right; } } function levelOrder(root) { if (!root) return []; const result = []; const queue = [root]; while (queue.length > 0) { const levelSize = queue.length; const currentLevel = []; for (let i = 0; i < levelSize; i++) { const node = queue.shift(); currentLevel.push(node.val); if (node.left) queue.push(node.left); if (node.right) queue.push(node.right); } result.push(currentLevel); } return result; } // Örnek: 3 -> [9, 20] -> [null, null, 15, 7] // Çıktı: [[3], [9, 20], [15, 7]]

Sıralı Diziyi Yükseklik Dengeli BST'ye Dönüştürme

Öğeleri artan sırada sıralanmış bir dizi verildiğinde, onu yükseklik dengeli bir ikili arama ağacına (BST) dönüştürün.

Açıklama: Yükseklik dengeli bir BST oluşturmak için, dizinin ortadaki öğesini kök olarak seçmelisiniz. Ardından, dizinin sol yarısından sol alt ağacı ve sağ yarısından sağ alt ağacı özyinelemeli olarak oluşturun.

class TreeNode { constructor(val = 0, left = null, right = null) { this.val = val; this.left = left; this.right = right; } } function sortedArrayToBST(nums) { if (!nums || nums.length === 0) return null; function buildBST(start, end) { if (start > end) return null; const mid = Math.floor((start + end) / 2); const node = new TreeNode(nums[mid]); node.left = buildBST(start, mid - 1); node.right = buildBST(mid + 1, end); return node; } return buildBST(0, nums.length - 1); } // Örnek: [-10, -3, 0, 5, 9] // Çıktı: [0, -3, 9, -10, null, 5, null] gibi bir ağaç

bind Uygulaması

Function.prototype.bind'ın kendi sürümünüzü uygulayın.

Açıklama: bind, çağrıldığında, this anahtar kelimesi sağlanan değere ayarlanmış ve yeni fonksiyon çağrıldığında sağlanan herhangi bir argümandan önce belirli bir argüman dizisiyle yeni bir fonksiyon oluşturur. Döndürülen bir fonksiyon içinde apply veya call kullanın, kısmi uygulamayı (önceden ayarlanmış argümanlar) ele alın.

Function.prototype.myBind = function(context, ...bindArgs) { const originalFunc = this; return function(...callArgs) { return originalFunc.apply(context, [...bindArgs, ...callArgs]); }; } const module = { x: 42, getX: function() { return this.x; } }; const unboundGetX = module.getX; console.log(unboundGetX()); // undefined (this genel/pencere) const boundGetX = unboundGetX.myBind(module); console.log(boundGetX()); // 42

K. En Büyük Elemanı Bulma

Sıralanmamış bir dizideki k. en büyük elemanı bulun. Bunun sıralı düzendeki k. en büyük eleman olduğunu, k. farklı eleman olmadığını unutmayın.

Açıklama: Basit bir yaklaşım, diziyi sıralamak ve ardından n - k dizinindeki öğeyi seçmektir. Büyük diziler için daha verimli bir yaklaşım, bir min-yığın veya Quickselect gibi bir seçim algoritması kullanmayı içerir.

function findKthLargest(nums, k) { // Basit yaklaşım: Sıralama nums.sort((a, b) => b - a); // Azalan sırada sırala return nums[k - 1]; // Not: Quickselect bir mülakatta daha verimli olacaktır // ancak sıralama hızlı bir şekilde uygulamak daha kolaydır. } console.log(findKthLargest([3, 2, 1, 5, 6, 4], 2)); // 5 console.log(findKthLargest([3, 2, 3, 1, 2, 4, 5, 5, 6], 4)); // 4

Nesnenin Özelliği Olup Olmadığını Kontrol Etme

Bir nesnenin belirli bir özelliğe sahip olup olmadığını nasıl kontrol edebilirsiniz?

Açıklama: in operatörünü (kendi ve kalıtsal özellikleri kontrol eder), Object.prototype.hasOwnProperty.call(obj, prop) (yalnızca kendi özellikleri kontrol eder) veya sadece obj.prop !== undefined (tanımsız değerlerle zor olabilir) kullanabilirsiniz.

const person = { name: 'Eve', age: 28 }; function hasProp(obj, prop) { console.log('in kullanarak: ' + (prop in obj)); console.log('hasOwnProperty kullanarak: ' + (Object.prototype.hasOwnProperty.call(obj, prop))); } hasProp(person, 'name'); // true, true hasProp(person, 'toString'); // true, false (toString kalıtsaldır)

Tamsayıdan Roma Rakamına

Bir tamsayıyı Roma rakamı gösterimine dönüştüren bir fonksiyon yazın.

Açıklama: Roma rakamlarının ve karşılık gelen değerlerinin bir haritasını oluşturun, en büyüğünden en küçüğüne doğru sıralayın. Bu harita boyunca yineleyin. Her değer için, giriş sayısından mümkün olduğunca çok kez çıkarın, her seferinde Roma rakamını ekleyin.

function intToRoman(num) { const map = { M: 1000, CM: 900, D: 500, CD: 400, C: 100, XC: 90, L: 50, XL: 40, X: 10, IX: 9, V: 5, IV: 4, I: 1 }; let result = ''; for (let key in map) { while (num >= map[key]) { result += key; num -= map[key]; } } return result; } console.log(intToRoman(3)); // III console.log(intToRoman(58)); // LVIII console.log(intToRoman(1994)); // MCMXCIV

Roma Rakamından Tamsayıya

Bir Roma rakamını bir tamsayıya dönüştüren bir fonksiyon yazın.

Açıklama: Roma sembollerini değerlere eşleyen bir harita oluşturun. Dizge boyunca yineleyin. Mevcut sembolün değeri bir sonraki sembolün değerinden küçükse (örneğin 'IV' veya 'IX'), mevcut değeri çıkarın; aksi takdirde ekleyin.

function romanToInt(s) { const map = { I: 1, V: 5, X: 10, L: 50, C: 100, D: 500, M: 1000 }; let result = 0; for (let i = 0; i < s.length; i++) { const currentVal = map[s[i]]; const nextVal = map[s[i + 1]]; if (nextVal > currentVal) { result -= currentVal; } else { result += currentVal; } } return result; } console.log(romanToInt('III')); // 3 console.log(romanToInt('LVIII')); // 58 console.log(romanToInt('MCMXCIV')); // 1994

Bir Set Uygulaması

Add, has, delete ve size metotlarına sahip temel bir Set veri yapısını (yerleşik Set kullanmadan) uygulayın.

Açıklama: Temel depolama olarak bir JavaScript nesnesi (hash haritası) kullanabilirsiniz. Anahtarlar küme öğeleri olacaktır (farklı türleri nasıl depolayacağınızı ve anahtar olarak benzersizliği nasıl sağlayacağınızı ele almanız gerekebilir).

class MySet { constructor() { this.items = {}; this._size = 0; } add(element) { if (!this.has(element)) { this.items[element] = element; // Öğeyi depola this._size++; return true; } return false; } delete(element) { if (this.has(element)) { delete this.items[element]; this._size--; return true; } return false; } has(element) { return Object.prototype.hasOwnProperty.call(this.items, element); } get size() { return this._size; } } const set = new MySet(); set.add(1); set.add(2); console.log(set.has(1)); // true console.log(set.size); // 2 set.delete(1); console.log(set.has(1)); // false

Pascal Üçgeni

Bir tamsayı numRows verildiğinde, Pascal üçgeninin ilk numRows'unu oluşturun.

Açıklama: Pascal üçgeninde, her sayı doğrudan üstündeki iki sayının toplamıdır. [[1]] ile başlayın. Her sonraki sıra için 1 ile başlayıp bitirin. Her orta eleman, üstteki sıradaki aynı dizindeki elemanın ve önceki dizindeki elemanın toplamıdır.

function generatePascalsTriangle(numRows) { if (numRows === 0) return []; const triangle = [[1]]; for (let i = 1; i < numRows; i++) { const prevRow = triangle[i - 1]; const newRow = [1]; for (let j = 1; j < i; j++) { newRow.push(prevRow[j - 1] + prevRow[j]); } newRow.push(1); triangle.push(newRow); } return triangle; } console.log(generatePascalsTriangle(5)); // [[1], [1, 1], [1, 2, 1], [1, 3, 3, 1], [1, 4, 6, 4, 1]]

Kelime Arama

2B bir tahta ve bir kelime verildiğinde, kelimenin ızgarada var olup olmadığını bulun. Kelime, bitişik hücrelerin harflerinden oluşturulabilir, burada 'bitişik' hücreler yatay veya dikey olarak komşudur.

Açıklama: Bu, geri izlemeli bir Derinlik Öncelikli Arama (DFS) gerektirir. Her hücre boyunca yineleyin. Bir hücre kelimenin ilk harfiyle eşleşiyorsa, bir DFS başlatın. DFS fonksiyonu komşuları kontrol eder, bir sonraki harfle eşleşmelerini ve mevcut yolda ziyaret edilmemiş olmalarını sağlar. Bir yol başarısız olursa, hücrenin işaretini kaldırarak geri izleyin.

function exist(board, word) { const rows = board.length; const cols = board[0].length; function dfs(r, c, index) { if (index === word.length) return true; // Kelime bulundu if (r < 0 || c < 0 || r >= rows || c >= cols || board[r][c] !== word[index]) { return false; } const temp = board[r][c]; board[r][c] = '#'; // Ziyaret edildi olarak işaretle const found = dfs(r + 1, c, index + 1) || dfs(r - 1, c, index + 1) || dfs(r, c + 1, index + 1) || dfs(r, c - 1, index + 1); board[r][c] = temp; // Geri izleme return found; } for (let r = 0; r < rows; r++) { for (let c = 0; c < cols; c++) { if (board[r][c] === word[0] && dfs(r, c, 0)) { return true; } } } return false; } const board = [['A','B','C','E'],['S','F','C','S'],['A','D','E','E']]; console.log(exist(board, 'ABCCED')); // true console.log(exist(board, 'SEE')); // true console.log(exist(board, 'ABCB')); // false

Minimum Pencere Alt Dizge

İki dizge s ve t verildiğinde, t'deki tüm karakterleri içerecek s'deki minimum pencereyi bulun. Eğer s'de t'deki tüm karakterleri kapsayan böyle bir pencere yoksa, boş dizge yi döndürün.

Açıklama: İki işaretçi (sol ve sağ) ve hash haritaları ile kayar pencere yaklaşımını kullanın. Bir harita t'den gerekli karakter sayımlarını depolar. Başka bir harita, mevcut penceredeki sayımları depolar. Sağ işaretçiyle pencereyi genişletin. Pencere gerekli tüm karakterleri içerdiğinde, mümkün olan en küçük pencereyi bulmak için sol işaretçiyle küçültmeye çalışın.

function minWindow(s, t) { if (!t || !s || s.length < t.length) return ''; const tMap = {}; for (const char of t) tMap[char] = (tMap[char] || 0) + 1; let required = Object.keys(tMap).length; let formed = 0; const windowMap = {}; let left = 0; let minLen = Infinity; let result = ''; for (let right = 0; right < s.length; right++) { const char = s[right]; windowMap[char] = (windowMap[char] || 0) + 1; if (tMap[char] && windowMap[char] === tMap[char]) { formed++; } while (left <= right && formed === required) { if (right - left + 1 < minLen) { minLen = right - left + 1; result = s.substring(left, right + 1); } const leftChar = s[left]; windowMap[leftChar]--; if (tMap[leftChar] && windowMap[leftChar] < tMap[leftChar]) { formed--; } left++; } } return result; } console.log(minWindow('ADOBECODEBANC', 'ABC')); // 'BANC'

Bağlı Listeyi Ters Çevirme

Tek yönlü bir bağlı listenin head'i verildiğinde, listeyi ters çevirin ve ters çevrilmiş listeyi döndürün.

Açıklama: Liste boyunca yineleyerek, her düğümün next işaretçisini önceki düğümü gösterecek şekilde değiştirmeniz gerekir. Yineleme sırasında previous, current ve next düğümlerini takip edin.

class ListNode { constructor(val = 0, next = null) { this.val = val; this.next = next; } } function reverseList(head) { let prev = null; let current = head; let next = null; while (current !== null) { next = current.next; // Sonraki düğümü depola current.next = prev; // Mevcut düğümün işaretçisini ters çevir prev = current; // Prev'i bir adım ileri taşı current = next; // Current'ı bir adım ileri taşı } return prev; // Yeni baş, son 'prev'dir } // Örnek: 1->2->3->4->5, 5->4->3->2->1 olur

Bağlı Listede Döngü Algılama

Bir bağlı listenin başı olan head verildiğinde, bağlı listede döngü olup olmadığını belirleyin.

Açıklama: 'Floyd'un Kaplumbağa ve Tavşan' algoritmasını kullanın. Bir adımda bir adım ilerleyen (slow) ve iki adımda iki adım ilerleyen (fast) iki işaretçi bulundurun. Eğer bir döngü varsa, fast işaretçisi sonunda slow işaretçisine yetişecektir.

class ListNode { constructor(val = 0, next = null) { this.val = val; this.next = next; } } function hasCycle(head) { if (!head || !head.next) return false; let slow = head; let fast = head.next; while (slow !== fast) { if (!fast || !fast.next) return false; // Sona ulaşıldı, döngü yok slow = slow.next; fast = fast.next.next; } return true; // İşaretçiler karşılaştı, döngü var } // Örnek: -4'ün 2'ye geri döndüğü 3->2->0->-4. hasCycle true döndürür.

Object.create Uygulaması

Object.create(proto) davranışını taklit eden bir fonksiyon uygulayın.

Açıklama: Object.create, yeni oluşturulan nesnenin prototipi olarak mevcut bir nesneyi kullanarak yeni bir nesne oluşturur. Bunu, geçici bir kurucu fonksiyon oluşturarak, prototipini proto'ya ayarlayarak ve ardından bunun yeni bir örneğini döndürerek başarabilirsiniz.

function myObjectCreate(proto) { if (typeof proto !== 'object' && typeof proto !== 'function') { if (proto !== null) { throw new TypeError('Object prototype may only be an Object or null: ' + proto); } } function F() {} F.prototype = proto; return new F(); } const person = { isHuman: false, printIntroduction: function() { console.log('Adım ' + this.name + '. İnsan mıyım? ' + this.isHuman); } }; const me = myObjectCreate(person); me.name = 'Matthew'; me.isHuman = true; me.printIntroduction(); // Adım Matthew. İnsan mıyım? true console.log(Object.getPrototypeOf(me) === person); // true

Hoisting Nedir?

JavaScript'te hoisting'i açıklayın ve bir örnek verin.

Açıklama: Hoisting, JavaScript'in bildirimleri kod yürütülmeden önce geçerli kapsamın (genel veya fonksiyon) en üstüne taşıma varsayılan davranışıdır. Değişken bildirimleri (var) yükseltilir ve undefined ile başlatılır. Fonksiyon bildirimleri tamamen yükseltilir (hem ad hem de gövde). let ve const yükseltilir ancak başlatılmaz, bu da Geçici Ölü Bölgeye yol açar.

console.log(myVar); // undefined (var yükseltilir ve undefined ile başlatılır) // console.log(myLet); // ReferenceError: myLet'e başlatılmadan önce erişilemez (TDZ) myFunc(); // 'Merhaba!' (Fonksiyon bildirimi tamamen yükseltilir) var myVar = 'Ben bir varım'; let myLet = 'Ben bir letim'; function myFunc() { console.log('Merhaba!'); }

Olay Kabarcıklanması ve Yakalanması Açıklaması

DOM bağlamında Olay Kabarcıklanmasını ve Yakalanmasını açıklayın.

Açıklama: Bunlar HTML DOM'daki olay yayılımının iki aşamasıdır. Yakalanma Aşaması: Olay, pencereden hedef öğeye doğru aşağı doğru hareket eder. Kabarcıklanma Aşaması: Olay, hedef öğeden pencereye doğru yukarı doğru hareket eder. Varsayılan olarak, çoğu olay işleyicisi kabarcıklanma aşamasında kaydedilir. Yakalanma aşamasında olayları ele almak için addEventListener(type, listener, useCapture) öğesini useCapture = true ile kullanabilirsiniz.

// Bir HTML yapısında: <div><p><span>Tıkla Bana</span></p></div> // <span>'ya tıklarsanız: // Yakalama: pencere -> belge -> html -> body -> div -> p -> span // Kabarcıklanma: span -> p -> div -> body -> html -> belge -> pencere /* JS Örnek div.addEventListener('click', () => console.log('Div tıklandı'), true); // Yakalama p.addEventListener('click', () => console.log('P tıklandı'), false); // Kabarcıklanma span.addEventListener('click', () => console.log('Span tıklandı'), false); // Kabarcıklanma // Çıktı şöyle olacaktır: Div tıklandı, Span tıklandı, P tıklandı */

JSON.parse'ı manuel olarak uygulayın (temel)

JSON.parse'ın çok temel bir sürümünü uygulamaya çalışın (basit nesneleri, dizileri, dizeleri, sayıları işleyin).

Açıklama: Bu, tam olarak çok karmaşık bir görevdir, ancak canlı kodlama ortamında çok basitleştirilmiş bir alt kümeyi ele almanız istenebilir. Dizgeyi ayrıştırmanız, nesne {} ve dizi [] sınırlarını, anahtar-değer çiftlerini (key: value) ve temel veri türlerini tanımlamanız gerekir. eval veya new Function bunu hileli bir şekilde yapabilir ancak tehlikelidir. Gerçek bir ayrıştırıcı bir sözlük/tokenleştirici ve ayrıştırıcı kullanacaktır.

function basicJsonParse(jsonString) { // UYARI: new Function kullanmak eval gibi güvensizdir. // Bu sadece gösterim amaçlı basitleştirilmiş, GÜVENSİZ bir örnektir. // Gerçek bir uygulama uygun bir ayrıştırıcı gerektirir. try { return (new Function('return ' + jsonString))(); } catch (e) { throw new SyntaxError('Geçersiz JSON: ' + e.message); } } console.log(basicJsonParse('{"a": 1, "b": ["x", "y"]}')); // { a: 1, b: ['x', 'y'] }

Derinlemesine İç İçe Diziyi Düzleştirme

Derinlemesine iç içe bir diziyi düzleştiren bir fonksiyon yazın.

Açıklama: Önceki düzleştirmeden (bir seviye) farklı olarak, bu her türlü iç içe geçmeyi ele almalıdır. Özyineleme doğal bir uyumdur. Dizi boyunca yineleyin. Eğer bir öğe bir diziyse, üzerinde özyinelemeli olarak düzleştirme çağrısı yapın ve sonucu birleştirin. Aksi takdirde, öğeyi ekleyin.

function deepFlatten(arr) { let flattened = []; arr.forEach(item => { if (Array.isArray(item)) { flattened = flattened.concat(deepFlatten(item)); } else { flattened.push(item); } }); return flattened; // ES2019+ çok daha basit bir yol sunar: // return arr.flat(Infinity); } console.log(deepFlatten([1, [2, [3, 4], 5], 6])); // [1, 2, 3, 4, 5, 6]

Trie (Önek Ağacı) Uygulaması

Ekle, ara ve ileBaşlar metotlarına sahip bir Trie veri yapısı uygulayın.

Açıklama: Bir Trie, dizelerden oluşan bir veri kümesindeki anahtarları verimli bir şekilde depolamak ve almak için kullanılan ağaç benzeri bir veri yapısıdır. Her düğüm bir karakteri temsil eder ve kökten gelen yollar kelimeleri veya önekleri temsil eder.

class TrieNode { constructor() { this.children = {}; this.isEndOfWord = false; } } class Trie { constructor() { this.root = new TrieNode(); } insert(word) { let node = this.root; for (const char of word) { if (!node.children[char]) { node.children[char] = new TrieNode(); } node = node.children[char]; } node.isEndOfWord = true; } search(word) { let node = this.root; for (const char of word) { if (!node.children[char]) return false; node = node.children[char]; } return node.isEndOfWord; } startsWith(prefix) { let node = this.root; for (const char of prefix) { if (!node.children[char]) return false; node = node.children[char]; } return true; } } const trie = new Trie(); trie.insert('apple'); console.log(trie.search('apple')); // true console.log(trie.search('app')); // false console.log(trie.startsWith('app')); // true

Bir Diziyi Karıştırma (Fisher-Yates)

Bir diziyi Fisher-Yates (veya Knuth) algoritmasını kullanarak yerinde karıştıran bir fonksiyon yazın.

Açıklama: Fisher-Yates algoritması, bir diziyi son öğeden ilk öğeye doğru yineler. Her yinelemede, mevcut öğeyi, dizinin başlangıcından mevcut öğeye (dahil) kadar rastgele seçilmiş bir öğeyle değiştirir.

function shuffleArray(arr) { for (let i = arr.length - 1; i > 0; i--) { const j = Math.floor(Math.random() * (i + 1)); [arr[i], arr[j]] = [arr[j], arr[i]]; // Öğeleri değiştir } return arr; } console.log(shuffleArray([1, 2, 3, 4, 5])); // örn., [3, 5, 1, 2, 4]

Fonksiyonları Birleştirme

Birden çok fonksiyon alan ve bunları sağdan sola uygulayan yeni bir fonksiyon döndüren bir compose fonksiyonu uygulayın.

Açıklama: Fonksiyon birleştirme (f ∘ g)(x) = f(g(x)) bir fonksiyonu diğerinin sonucuna uygular. Genel bir compose(f, g, h) f(g(h(x))) anlamına gelir. Zarif bir uygulama için reduceRight'ı kullanın.

function compose(...funcs) { return function(initialArg) { return funcs.reduceRight((acc, func) => func(acc), initialArg); }; } const add5 = x => x + 5; const multiply3 = x => x * 3; const subtract2 = x => x - 2; const composedFunc = compose(subtract2, multiply3, add5); console.log(composedFunc(10)); // (10 + 5) * 3 - 2 = 15 * 3 - 2 = 45 - 2 = 43

Fonksiyonları Borulama

Birden çok fonksiyon alan ve bunları soldan sağa uygulayan yeni bir fonksiyon döndüren bir pipe fonksiyonu uygulayın.

Açıklama: compose'a benzer, ancak uygulama sırası tersine çevrilmiştir: pipe(f, g, h) h(g(f(x))) anlamına gelir. Uygulama için reduce kullanın.

function pipe(...funcs) { return function(initialArg) { return funcs.reduce((acc, func) => func(acc), initialArg); }; } const add5 = x => x + 5; const multiply3 = x => x * 3; const subtract2 = x => x - 2; const pipedFunc = pipe(add5, multiply3, subtract2); console.log(pipedFunc(10)); // (10 + 5) * 3 - 2 = 15 * 3 - 2 = 45 - 2 = 43

Madeni Para Değiştirme Problemi

Madeni para birimlerinin bir dizisi ve bir miktar verildiğinde, bu miktarı oluşturmak için gereken minimum madeni para sayısını bulun. Her madeni paradan sonsuz sayıda olduğunu varsayın.

Açıklama: Bu klasik bir dinamik programlama problemidir. dp[i]'nin i miktarı için gereken minimum madeni paraları depoladığı bir dp dizisi oluşturun. dp[i] = min(dp[i - coin]) + 1 tüm paralar için.

function coinChange(coins, amount) { const dp = new Array(amount + 1).fill(Infinity); dp[0] = 0; for (let i = 1; i <= amount; i++) { for (const coin of coins) { if (i - coin >= 0) { dp[i] = Math.min(dp[i], dp[i - coin] + 1); } } } return dp[amount] === Infinity ? -1 : dp[amount]; } console.log(coinChange([1, 2, 5], 11)); // 3 (5 + 5 + 1) console.log(coinChange([2], 3)); // -1

En Düşük Ortak Ata (BST)

Bir ikili arama ağacı (BST) verildiğinde, BST'deki iki verilen düğümün en düşük ortak atasını (LCA) bulun.

Açıklama: LCA, her iki verilen düğümü de torun olarak içeren en derin düğümdür. Bir BST'de, kökten geçerek bulunabilir. Her iki düğüm de mevcut düğümden küçükse, sola gidin. Her ikisi de büyükse, sağa gidin. Eğer biri küçük diğeri büyükse (veya biri mevcut düğümse), o zaman mevcut düğüm LCA'dır.

class Node { constructor(val) { this.val = val; this.left = this.right = null; } } function lowestCommonAncestor(root, p, q) { let current = root; while (current) { if (p.val > current.val && q.val > current.val) { current = current.right; } else if (p.val < current.val && q.val < current.val) { current = current.left; } else { return current; // LCA bulundu } } return null; // p ve q ile geçerli bir BST'de olmamalıdır } // Örnek: root = [6,2,8,0,4,7,9,null,null,3,5], p = 2, q = 8 => LCA 6'dır

İkili Ağacı Serileştirme ve Seri Halden Çıkarma

İkili bir ağacı serileştirmek ve seri halden çıkarmak için bir algoritma tasarlayın.

Açıklama: Serileştirme bir ağacı bir dizgeye veya diziye dönüştürür. Seri halden çıkarma ağacı yeniden oluşturur. Yaygın bir yol Ön Sıra Geçişidir (DFS). Yapıyı korumak için boş düğümler için özel bir işaretleyici (örn. '#') kullanın.

class Node { constructor(val) { this.val = val; this.left = this.right = null; } } function serialize(root) { const values = []; function dfs(node) { if (!node) { values.push('#'); return; } values.push(node.val); dfs(node.left); dfs(node.right); } dfs(root); return values.join(','); } function deserialize(data) { const values = data.split(','); let index = 0; function buildTree() { if (values[index] === '#') { index++; return null; } const node = new Node(parseInt(values[index])); index++; node.left = buildTree(); node.right = buildTree(); return node; } return buildTree(); } // Örnek: 1 -> [2, 3] -> [null, null, 4, 5] // Serileştirilmiş: '1,2,#,#,3,4,#,#,5,#,#'

setTimeout ile setInterval Uygulaması

setInterval'ı taklit eden ancak setTimeout'u özyinelemeli olarak kullanan bir mySetInterval fonksiyonu uygulayın.

Açıklama: setInterval bir fonksiyonu her N milisaniyede bir tekrar tekrar çalıştırır. Bunu, bir fonksiyonun her yürütmeden sonra setTimeout ile kendisini çağırmasıyla başarabilirsiniz. Ayrıca bunu temizlemenin bir yoluna da ihtiyacınız var (myClearInterval).

function mySetInterval(callback, delay, ...args) { const interval = { timerId: null }; function run() { interval.timerId = setTimeout(() => { callback.apply(this, args); run(); // Bir sonraki çağrıyı planla }, delay); } run(); return interval; // Temizlemeye izin vermek için bir nesne döndürün } function myClearInterval(interval) { clearTimeout(interval.timerId); } // Örnek kullanım: let count = 0; const intervalId = mySetInterval(() => { console.log('Merhaba: ' + (++count)); if (count === 3) myClearInterval(intervalId); }, 500);

Grafik Geçişi (BFS ve DFS)

Verilen bir grafik (komşuluk listesi gösterimi) için Genişlik Öncelikli Arama (BFS) ve Derinlik Öncelikli Arama (DFS) uygulayın.

Açıklama: BFS öncelikle komşuları keşfeder (bir Kuyruk kullanarak), DFS ise her dal boyunca mümkün olduğunca uzağa keşfeder (bir Yığın veya özyineleme kullanarak). Döngülerden ve gereksiz çalışmalardan kaçınmak için ziyaret edilen düğümleri takip edin.

const graph = { A: ['B', 'C'], B: ['D'], C: ['E'], D: [], E: ['F'], F: [] }; function bfs(graph, startNode) { const queue = [startNode]; const visited = new Set(); const result = []; visited.add(startNode); while (queue.length > 0) { const node = queue.shift(); result.push(node); for (const neighbor of graph[node]) { if (!visited.has(neighbor)) { visited.add(neighbor); queue.push(neighbor); } } } return result; } function dfs(graph, startNode) { const stack = [startNode]; const visited = new Set(); const result = []; while (stack.length > 0) { const node = stack.pop(); if (!visited.has(node)) { visited.add(node); result.push(node); // Komşuları daha sonra sırayla işlemek için ters sırada ekleyin (isteğe bağlı) for (let i = graph[node].length - 1; i >= 0; i--) { stack.push(graph[node][i]); } } } return result; } console.log('BFS:', bfs(graph, 'A')); // ['A', 'B', 'C', 'D', 'E', 'F'] console.log('DFS:', dfs(graph, 'A')); // ['A', 'B', 'D', 'C', 'E', 'F']

Görüntüyü Döndürme (Matris)

Bir görüntüyü temsil eden n x n 2D bir matris verildiğinde. Görüntüyü 90 derece (saat yönünde) yerinde döndürün.

Açıklama: Bunu başarmanın yaygın bir yolu, önce matrisi devirmek (matrix[i][j]'yi matrix[j][i] ile değiştirmek) ve ardından her satırı tersine çevirmektir.

function rotate(matrix) { const n = matrix.length; // Devir for (let i = 0; i < n; i++) { for (let j = i; j < n; j++) { [matrix[i][j], matrix[j][i]] = [matrix[j][i], matrix[i][j]]; } } // Her satırı ters çevir for (let i = 0; i < n; i++) { matrix[i].reverse(); } return matrix; } const matrix = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]; console.log(rotate(matrix)); // [[7, 4, 1], [8, 5, 2], [9, 6, 3]]

Sarmal Matris Dolaşımı

m x n boyutunda bir matris verildiğinde, matrisin tüm elemanlarını sarmal sırayla döndürün.

Açıklama: Sınırları tanımlamak için dört işaretçi kullanın: top, bottom, left, right. En üst satırı, ardından sağ sütunu, ardından alt satırı ve ardından sol sütunu dolaşın. Her dolaşımdan sonra sınırları daraltın, ta ki left right ı veya top bottom u geçene kadar.

function spiralOrder(matrix) { if (!matrix || matrix.length === 0) return []; const rows = matrix.length, cols = matrix[0].length; const result = []; let top = 0, bottom = rows - 1, left = 0, right = cols - 1; while (top <= bottom && left <= right) { for (let i = left; i <= right; i++) result.push(matrix[top][i]); top++; for (let i = top; i <= bottom; i++) result.push(matrix[i][right]); right--; if (top <= bottom) { for (let i = right; i >= left; i--) result.push(matrix[bottom][i]); bottom--; } if (left <= right) { for (let i = bottom; i >= top; i--) result.push(matrix[i][left]); left++; } } return result; } const matrix = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]; console.log(spiralOrder(matrix)); // [1, 2, 3, 6, 9, 8, 7, 4, 5]

Matrisi Sıfırla

m x n boyutunda bir matris verildiğinde, bir eleman 0 ise, o elemanın tüm satırını ve sütununu 0 yapın. Bunu yerinde yapın.

Açıklama: Saf bir yaklaşım O(m*n) ek alan gerektirir. Bunu O(1) alanda (veya O(m+n)) yapmak için, hangi satırların/sütunların sıfırlanması gerektiği bilgisini depolamak için ilk satırı ve ilk sütunu kullanabilirsiniz. İlk satırın/sütunun kendilerinin sıfırlanması gerekip gerekmediği için ayrı bayraklar gereklidir.

function setZeroes(matrix) { const rows = matrix.length, cols = matrix[0].length; let firstColZero = false; for (let r = 0; r < rows; r++) { if (matrix[r][0] === 0) firstColZero = true; for (let c = 1; c < cols; c++) { if (matrix[r][c] === 0) { matrix[r][0] = 0; matrix[0][c] = 0; } } } for (let r = rows - 1; r >= 0; r--) { for (let c = cols - 1; c >= 1; c--) { if (matrix[r][0] === 0 || matrix[0][c] === 0) { matrix[r][c] = 0; } } if (firstColZero) matrix[r][0] = 0; } return matrix; } // Örnek: [[1,1,1],[1,0,1],[1,1,1]] => [[1,0,1],[0,0,0],[1,0,1]]

Promise.race Uygulaması

Promise.race gibi davranan bir fonksiyon uygulayın.

Açıklama: Promise.race bir dizi promise alır ve tek bir promise döndürür. Bu döndürülen promise, herhangi bir girdi promise i çözüldüğü (resolved) veya reddedildiği (rejected) anda, o promise den gelen değer veya neden ile çözülür.

function myPromiseRace(promises) { return new Promise((resolve, reject) => { if (!promises || promises.length === 0) { return; // Veya spesifikasyona göre resolve/reject } promises.forEach(promise => { Promise.resolve(promise).then(resolve, reject); }); }); } const p1 = new Promise((resolve) => setTimeout(resolve, 500, 'one')); const p2 = new Promise((resolve) => setTimeout(resolve, 100, 'two')); myPromiseRace([p1, p2]).then(value => console.log(value)); // 'two'

Singleton Kalıbı

JavaScript te Singleton tasarım kalıbını uygulayın.

Açıklama: Singleton kalıbı, bir sınıfın yalnızca bir örneğe sahip olmasını sağlar ve ona küresel bir erişim noktası sunar. Bu, örneği tutmak için bir closure kullanılarak başarılabilir.

const Singleton = (function() { let instance; function createInstance() { // Özel metotlar ve değişkenler const privateVar = 'I am private'; function privateMethod() { console.log('Private'); } return { // Genel metotlar ve değişkenler publicVar: 'I am public', publicMethod: function() { console.log('Public'); }, getPrivate: function() { return privateVar; } }; } return { getInstance: function() { if (!instance) { instance = createInstance(); } return instance; } }; })(); const instance1 = Singleton.getInstance(); const instance2 = Singleton.getInstance(); console.log(instance1 === instance2); // true console.log(instance1.getPrivate()); // 'I am private'

IP Adresi Doğrulama

Verilen bir dizenin geçerli bir IPv4 veya IPv6 adresi olup olmadığını kontrol eden bir fonksiyon yazın.

Açıklama: IPv4 için, noktalarla ayrılmış 4 sayı (0-255) olup olmadığını kontrol edin, baştaki sıfırlar olmasın ('0' hariç). IPv6 için, iki nokta üst üste ile ayrılmış 1-4 onaltılık basamak içeren 8 grup olup olmadığını kontrol edin ('::' gibi varyasyonları ele alın). Regex kullanılabilir, ancak manuel ayrıştırma genellikle mülakatlar için daha açıktır.

function validIPAddress(IP) { function isIPv4(s) { const parts = s.split('.'); if (parts.length !== 4) return false; for (const part of parts) { if (!/^[0-9]+$/.test(part)) return false; if (part.length > 1 && part.startsWith('0')) return false; const num = parseInt(part); if (num < 0 || num > 255) return false; } return true; } function isIPv6(s) { const parts = s.split(':'); if (parts.length !== 8) return false; // Basitleştirilmiş: '::' yok for (const part of parts) { if (part.length < 1 || part.length > 4) return false; if (!/^[0-9a-fA-F]+$/.test(part)) return false; } return true; } if (IP.includes('.')) return isIPv4(IP) ? 'IPv4' : 'Neither'; if (IP.includes(':')) return isIPv6(IP) ? 'IPv6' : 'Neither'; return 'Neither'; } console.log(validIPAddress('172.16.254.1')); // IPv4 console.log(validIPAddress('2001:0db8:85a3:0000:0000:8a2e:0370:7334')); // IPv6 (Basitleştirilmiş) console.log(validIPAddress('256.256.256.256')); // Neither

Zirve Elemanı Bul

Bir zirve elemanı, komşularından kesinlikle daha büyük olan bir elemandır. nums adında bir girdi dizisi verildiğinde, bir zirve elemanı bulun ve indeksini döndürün.

Açıklama: Herhangi bir zirve yeterli olacağından ve nums[-1] ile nums[n] -Sonsuz olarak kabul edildiğinden, değiştirilmiş bir ikili arama kullanabilirsiniz. Eğer nums[mid] nums[mid+1] den küçükse, sağda bir zirve olmalıdır. Aksi takdirde, solda bir zirve olmalıdır (veya mid in kendisi bir zirvedir).

function findPeakElement(nums) { let left = 0; let right = nums.length - 1; while (left < right) { let mid = Math.floor((left + right) / 2); if (nums[mid] < nums[mid + 1]) { left = mid + 1; // Zirve sağdadır } else { right = mid; // Zirve mid veya soldadır } } return left; // 'left' bir zirvenin indeksi olacaktır } console.log(findPeakElement([1, 2, 3, 1])); // 2 (3'ün indeksi) console.log(findPeakElement([1, 2, 1, 3, 5, 6, 4])); // 5 (6'nın indeksi) veya 1 (2'nin indeksi)

Bit Sayma

Bir tamsayı n verildiğinde, uzunluğu n + 1 olan bir ans dizisi döndürün; öyle ki her i (0 <= i <= n) için, ans[i], i nin ikili gösterimindeki 1 lerin sayısıdır.

Açıklama: Bunu dinamik programlama kullanarak çözebilirsiniz. İlişkiye dikkat edin: dp[i] = dp[i >> 1] + (i & 1). i deki 1 lerin sayısı, i nin sağa kaydırılmış halindeki (yani, i/2) 1 lerin sayısı artı i tekse 1 dir.

function countBits(n) { const dp = new Array(n + 1).fill(0); for (let i = 1; i <= n; i++) { dp[i] = dp[i >> 1] + (i & 1); // Veya: dp[i] = dp[i & (i - 1)] + 1; (Son ayarlı biti kaldırır) } return dp; } console.log(countBits(5)); // [0, 1, 1, 2, 1, 2]

İkinin Kuvveti

Bir tamsayı n verildiğinde, ikinin kuvveti ise true döndürün. Aksi takdirde, false döndürün.

Açıklama: İkili gösterimde ikinin kuvveti tam olarak bir '1' bite sahiptir (örneğin, 1=1, 2=10, 4=100, 8=1000). Akıllı bir bit tabanlı hile, n > 0 ve (n & (n - 1)) === 0 olup olmadığını kontrol etmektir. Eğer n ikinin kuvvetiyse, n-1 o '1' in altındaki tüm bitleri '1' olarak ayarlayacaktır. Bunları VElemek 0 sonucunu verir.

function isPowerOfTwo(n) { return n > 0 && (n & (n - 1)) === 0; } console.log(isPowerOfTwo(16)); // true console.log(isPowerOfTwo(1)); // true console.log(isPowerOfTwo(18)); // false

Aralıkları Birleştir

intervals[i] = [starti, endi] şeklinde toplantı zaman aralıkları dizisi verildiğinde, çakışan tüm aralıkları birleştirin ve çakışmayan aralıkların bir dizisini döndürün.

Açıklama: İlk olarak, aralıkları başlangıç zamanlarına göre sıralayın. Ardından, sıralanmış aralıklar üzerinde yineleyin. Eğer geçerli aralık, sonuç listesindeki son aralıkla çakışıyorsa, son aralığın bitiş zamanını güncelleyerek bunları birleştirin. Aksi takdirde, geçerli aralığı sonuç listesine ekleyin.

function mergeIntervals(intervals) { if (intervals.length === 0) return []; intervals.sort((a, b) => a[0] - b[0]); const merged = [intervals[0]]; for (let i = 1; i < intervals.length; i++) { const last = merged[merged.length - 1]; const current = intervals[i]; if (current[0] <= last[1]) { // Çakışma: birleştir last[1] = Math.max(last[1], current[1]); } else { // Çakışma yok: yeni aralık ekle merged.push(current); } } return merged; } console.log(mergeIntervals([[1, 3], [2, 6], [8, 10], [15, 18]])); // [[1, 6], [8, 10], [15, 18]]

Kelime Bölme

Bir s dizisi ve bir wordDict dizisi verildiğinde, s nin bir veya daha fazla sözlük kelimesinin boşlukla ayrılmış bir dizisi olarak bölümlenebiliyorsa true döndürün.

Açıklama: Dinamik programlama kullanın. dp[i] nin s[0...i-1] alt dizisinin bölümlenebiliyorsa doğru olduğu bir boole dizisi dp oluşturun. dp[i], j < i için dp[j] doğruysa ve s[j...i-1] alt dizisi sözlükte varsa doğrudur.

function wordBreak(s, wordDict) { const wordSet = new Set(wordDict); const n = s.length; const dp = new Array(n + 1).fill(false); dp[0] = true; // Temel durum: boş dize for (let i = 1; i <= n; i++) { for (let j = 0; j < i; j++) { if (dp[j] && wordSet.has(s.substring(j, i))) { dp[i] = true; break; } } } return dp[n]; } console.log(wordBreak('leetcode', ['leet', 'code'])); // true console.log(wordBreak('applepenapple', ['apple', 'pen'])); // true console.log(wordBreak('catsandog', ['cats', 'dog', 'sand', 'and', 'cat'])); // false

Array.prototype.flat Uygulaması

Array.prototype.flat ın kendi sürümünüzü uygulayın, bu sürüm belirtilen bir derinliğe kadar tüm alt dizi elemanlarını özyinelemeli olarak birleştirerek yeni bir dizi oluşturur.

Açıklama: Özyineleme kullanın. Dizi üzerinde yineleyin. Eğer bir eleman bir diziyse ve geçerli derinlik belirtilen derinlikten küçükse, üzerinde özyinelemeli olarak düzleştirme çağrısı yapın. Aksi takdirde, elemanı push edin. Varsayılan derinlik olan 1 i ele alın.

function myFlat(arr, depth = 1) { let flattened = []; arr.forEach(item => { if (Array.isArray(item) && depth > 0) { flattened.push(...myFlat(item, depth - 1)); } else { flattened.push(item); } }); return flattened; } console.log(myFlat([1, [2, [3, 4], 5], 6])); // [2, [3, 4], 5] console.log(myFlat([1, [2, [3, 4], 5], 6], 2)); // [1, 2, 3, 4, 5, 6]

Bir Dizedeki Kelimeleri Ters Çevir

Bir girdi dizisi s verildiğinde, kelimelerin sırasını ters çevirin.

Açıklama: 'Kelime', boşluk olmayan karakter dizisi olarak tanımlanır. Diziyi kırpın, bir veya daha fazla boşlukla ayırın, çoklu boşluklardan kaynaklanan boş dizeleri filtreleyin, diziyi ters çevirin ve tek boşluklarla tekrar birleştirin.

function reverseWords(s) { return s.trim().split(/\s+/).reverse().join(' '); } console.log(reverseWords('the sky is blue')); // 'blue is sky the' console.log(reverseWords(' hello world ')); // 'world hello' console.log(reverseWords('a good example')); // 'example good a'

Sorgu Dizesi Ayrıştırıcı

Bir URL sorgu dizisini bir nesneye ayrıştırmak için bir fonksiyon yazın.

Açıklama: Diziyi & ile ayırın. Her bölüm için, anahtar ve değeri almak için = ile ayırın. Hem anahtar hem de değer için URI bileşenlerini çözün. Bir anahtarın birden çok kez görünebileceği (bir dizi oluşturun) veya hiçbir değeri olmayan durumları ele alın.

function parseQueryString(query) { if (query.startsWith('?')) { query = query.substring(1); } const result = {}; if (!query) return result; query.split('&').forEach(pair => { const [key, value] = pair.split('='); const decodedKey = decodeURIComponent(key); const decodedValue = value !== undefined ? decodeURIComponent(value) : true; if (result.hasOwnProperty(decodedKey)) { if (Array.isArray(result[decodedKey])) { result[decodedKey].push(decodedValue); } else { result[decodedKey] = [result[decodedKey], decodedValue]; } } else { result[decodedKey] = decodedValue; } }); return result; } console.log(parseQueryString('?foo=bar&baz=qux&baz=quux&corge')); // { foo: 'bar', baz: ['qux', 'quux'], corge: true }

Doğrulama İçin Proxy Kullanımı

Nesne özelliği doğrulaması için bir Proxy nesnesinin nasıl kullanılacağını gösterin.

Açıklama: Bir Proxy, bir nesne üzerinde gerçekleştirilen işlemleri yakalamanıza ve özelleştirmenize olanak tanır. Değerleri bir özelliğe atamadan önce doğrulamak için set tuzağını kullanın. Doğrulama başarısız olursa bir hata fırlatın.

const validator = { set: function(obj, prop, value) { if (prop === 'age') { if (!Number.isInteger(value)) { throw new TypeError('The age is not an integer'); } if (value < 0 || value > 150) { throw new RangeError('The age seems invalid'); } } // Varsayılan davranış: Özelliği ayarla obj[prop] = value; return true; } }; const person = {}; const personProxy = new Proxy(person, validator); personProxy.age = 30; // OK console.log(personProxy.age); // 30 // personProxy.age = 'thirty'; // TypeError fırlatır // personProxy.age = 200; // RangeError fırlatır

Toplantı Odaları

Toplantı zaman aralıklarının [[start1, end1], [start2, end2], ...] dizisi verildiğinde, bir kişinin tüm toplantılara katılıp katılamayacağını belirleyin.

Açıklama: Eğer bir kişi tüm toplantılara katılabiliyorsa, bu, hiçbir iki toplantının çakışmadığı anlamına gelir. Bunu kontrol etmek için, aralıkları başlangıç zamanlarına göre sıralayın. Ardından, sıralanmış aralıklar üzerinde yineleyin ve geçerli toplantının başlangıç zamanının önceki toplantının bitiş zamanından önce olup olmadığını kontrol edin. Eğer öyleyse, bir çakışma var demektir ve kişi tüm toplantılara katılamaz.

function canAttendMeetings(intervals) { if (intervals.length < 2) return true; intervals.sort((a, b) => a[0] - b[0]); for (let i = 1; i < intervals.length; i++) { if (intervals[i][0] < intervals[i - 1][1]) { return false; // Çakışma tespit edildi } } return true; } console.log(canAttendMeetings([[0, 30], [5, 10], [15, 20]])); // false (5<30) console.log(canAttendMeetings([[7, 10], [2, 4]])); // true

Promise.any Uygulaması

Promise.any gibi davranan bir fonksiyon uygulayın.

Açıklama: Promise.any bir dizi promise alır ve tek bir promise döndürür. Bu promise, herhangi bir girdi promise i çözülür çözülmez yerine getirilir. Eğer tüm girdi promiseleri reddedilirse, tüm reddetme nedenlerini içeren bir AggregateError ile reddedilir.

function myPromiseAny(promises) { return new Promise((resolve, reject) => { const numPromises = promises.length; if (numPromises === 0) { reject(new AggregateError([], 'All promises were rejected')); return; } let rejectionCount = 0; const errors = []; promises.forEach((promise, index) => { Promise.resolve(promise) .then(resolve) // Bir tanesi yerine getirilir getirilmez çöz .catch(error => { errors[index] = error; rejectionCount++; if (rejectionCount === numPromises) { reject(new AggregateError(errors, 'All promises were rejected')); } }); }); }); } // Örnek: myPromiseAny([Promise.reject('err1'), Promise.resolve('ok')]) -> 'ok' // Örnek: myPromiseAny([Promise.reject('err1'), Promise.reject('err2')]) -> AggregateError

Gözlemci Kalıbı

JavaScript te Gözlemci (Pub/Sub) tasarım kalıbını uygulayın.

Açıklama: Gözlemci kalıbı, nesneler arasında bire çok bağımlılık tanımlar. Bir nesne (Özne) durum değiştirdiğinde, tüm bağımlılıkları (Gözlemciler) otomatik olarak bilgilendirilir ve güncellenir. Özne, bir gözlemci listesini tutar ve bunları ekleme, kaldırma ve bilgilendirme yöntemleri sağlar.

class Subject { constructor() { this.observers = []; } subscribe(observer) { this.observers.push(observer); } unsubscribe(observer) { this.observers = this.observers.filter(obs => obs !== observer); } notify(data) { this.observers.forEach(observer => observer.update(data)); } } class Observer { constructor(name) { this.name = name; } update(data) { console.log(`${this.name} received: ${data}`); } } const subject = new Subject(); const obs1 = new Observer('Observer 1'); const obs2 = new Observer('Observer 2'); subject.subscribe(obs1); subject.subscribe(obs2); subject.notify('Something happened!'); // Observer 1 received: Something happened! // Observer 2 received: Something happened!

Tekrar Eden Sayıyı Bul

[1, n] aralığında her bir tamsayının bulunduğu n + 1 tamsayı içeren bir nums tamsayı dizisi verildiğinde, tekrar eden sayıyı bulun.

Açıklama: Sayılar [1, n] aralığında olduğundan ve dizinin boyutu n+1 olduğundan, en az bir tekrar eden sayının olması garanti edilir. Bu, Bağlı Listede Döngü Bulma (Floyd'un Kaplumbağa ve Tavşan) problemine eşleştirilebilir. Dizi değerlerini işaretçi olarak düşünün: index -> nums[index].

function findDuplicate(nums) { let tortoise = nums[0]; let hare = nums[0]; // Aşama 1: Kesişim noktasını bul do { tortoise = nums[tortoise]; hare = nums[nums[hare]]; } while (tortoise !== hare); // Aşama 2: Döngünün girişini bul let ptr1 = nums[0]; let ptr2 = tortoise; while (ptr1 !== ptr2) { ptr1 = nums[ptr1]; ptr2 = nums[ptr2]; } return ptr1; } console.log(findDuplicate([1, 3, 4, 2, 2])); // 2 console.log(findDuplicate([3, 1, 3, 4, 2])); // 3

Temel HTML Temizleyici

Potansiyel olarak zararlı etiketleri (script gibi) güvenli etiketleri (p, b gibi) koruyarak kaldıran temel bir HTML dizesi temizleme fonksiyonu yazın.

Açıklama: Bu karmaşık bir konudur ve gerçek dünya temizleyicileri oldukça gelişmiştir. Bir mülakat için, temel bir yaklaşım, belirli etiketleri kaldırmak veya yalnızca beyaz listeye alınmış etiketlere izin vermek için Regex kullanmayı içerebilir. Bu üretim için güvenli değildir.

function basicSanitize(html) { // UYARI: Bu çok temel ve güvensiz bir örnektir. // Üretimde KULLANMAYIN. DOMPurify gibi bir kütüphane kullanın. // script etiketlerini kaldır let sanitized = html.replace(/<script\b[^<]*(?:(?!<\/script>)<[^<]*)*<\/script>/gi, ''); // Örnek: onclick özniteliklerini kaldır (çok temel) sanitized = sanitized.replace(/\s(on\w+)=['"]?[^'"]*['"]?/gi, ''); return sanitized; } console.log(basicSanitize('<p>Hello <script>alert("XSS")</script> <b onclick="danger()">World</b></p>')); // <p>Hello <b >World</b></p>

Düzenleme Mesafesi

İki dize word1 ve word2 verildiğinde, word1 i word2 ye dönüştürmek için gereken minimum işlem (ekleme, silme veya değiştirme) sayısını döndürün.

Açıklama: Bu klasik bir dinamik programlama problemidir (Levenshtein mesafesi). dp[i][j] nin word1 in ilk i karakteri ile word2 nin ilk j karakteri arasındaki düzenleme mesafesi olduğu bir 2D dizi dp oluşturun. Rekürans ilişkisi, ekleme, silme ve değiştirme maliyetini dikkate almayı içerir.

function minDistance(word1, word2) { const m = word1.length, n = word2.length; const dp = Array(m + 1).fill(null).map(() => Array(n + 1).fill(0)); for (let i = 0; i <= m; i++) dp[i][0] = i; for (let j = 0; j <= n; j++) dp[0][j] = j; for (let i = 1; i <= m; i++) { for (let j = 1; j <= n; j++) { const cost = word1[i - 1] === word2[j - 1] ? 0 : 1; dp[i][j] = Math.min( dp[i - 1][j] + 1, // Silme dp[i][j - 1] + 1, // Ekleme dp[i - 1][j - 1] + cost // Değiştirme/Eşleşme ); } } return dp[m][n]; } console.log(minDistance('horse', 'ros')); // 3 console.log(minDistance('intention', 'execution')); // 5

En Uzun Artan Alt Dizi (LIS)

Bir tamsayı dizisi nums verildiğinde, en uzun kesinlikle artan alt dizinin uzunluğunu döndürün.

Açıklama: Dinamik programlama kullanın. dp[i] nin i indeksinde biten LIS in uzunluğu olduğunu varsayalım. dp[i] yi hesaplamak için, nums[j] < nums[i] olacak şekilde tüm j < i yi bulun ve dp[i] = 1 + max(dp[j]) alın. Son cevap, dp dizisindeki maksimum değerdir.

function lengthOfLIS(nums) { if (nums.length === 0) return 0; const n = nums.length; const dp = new Array(n).fill(1); let maxLength = 1; for (let i = 1; i < n; i++) { for (let j = 0; j < i; j++) { if (nums[i] > nums[j]) { dp[i] = Math.max(dp[i], dp[j] + 1); } } maxLength = Math.max(maxLength, dp[i]); } return maxLength; } console.log(lengthOfLIS([10, 9, 2, 5, 3, 7, 101, 18])); // 4 (2, 3, 7, 101)

N-Kraliçe Problemi

N-Kraliçe problemi, N satranç kraliçesinin N×N bir satranç tahtasına, hiçbir iki kraliçenin birbirini tehdit etmeyecek şekilde yerleştirilmesi problemidir. N verildiğinde, bir geçerli çözüm (veya tüm çözümleri) döndürün.

Açıklama: Geri izleme kullanın. Kraliçeleri satır satır yerleştirin. Her satır için, her sütuna bir kraliçe yerleştirmeyi deneyin. Yerleştirmeden önce, önerilen konumun güvenli olup olmadığını kontrol edin (önceki satırlardaki kraliçeler tarafından saldırıya uğramamış). Güvenliyse, onu yerleştirin ve bir sonraki satır için tekrarlayın. Eğer özyineleme başarısız olursa, geri izleyin (kraliçeyi kaldırın) ve bir sonraki sütunu deneyin.

function solveNQueens(n) { const results = []; const board = Array(n).fill('.').map(() => Array(n).fill('.')); function isSafe(row, col) { for (let i = 0; i < row; i++) if (board[i][col] === 'Q') return false; // Sütunu kontrol et for (let i = row - 1, j = col - 1; i >= 0 && j >= 0; i--, j--) if (board[i][j] === 'Q') return false; // Çapraz yukarı-solu kontrol et for (let i = row - 1, j = col + 1; i >= 0 && j < n; i--, j++) if (board[i][j] === 'Q') return false; // Çapraz yukarı-sağı kontrol et return true; } function backtrack(row) { if (row === n) { results.push(board.map(r => r.join(''))); return; } for (let col = 0; col < n; col++) { if (isSafe(row, col)) { board[row][col] = 'Q'; backtrack(row + 1); board[row][col] = '.'; // Geri izle } } } backtrack(0); return results; } console.log(solveNQueens(4)); // [ [ '.Q..', '...Q', 'Q...', '..Q.' ], [ '..Q.', 'Q...', '...Q', '.Q..' ] ]

Özel Veriler İçin WeakMap Kullanımı

Sınıf örnekleri için özel verileri depolamak için WeakMap in nasıl kullanılacağını gösterin.

Açıklama: WeakMap, bir nesneye, nesneye artık referans verilmediğinde çöp toplamasını engellemeyecek şekilde veri atamanıza olanak tanır. Bu, JavaScript sınıflarında yerel özel alanlar yaygın olarak kullanılmadan önce veya belirli kullanım durumları için özel üyeler oluşturmak için kullanışlıdır.

const privateData = new WeakMap(); class Person { constructor(name, age) { privateData.set(this, { name: name, age: age }); } getName() { return privateData.get(this).name; } getAge() { return privateData.get(this).age; } celebrateBirthday() { privateData.get(this).age++; } } const person = new Person('Alice', 30); console.log(person.getName()); // Alice person.celebrateBirthday(); console.log(person.getAge()); // 31 // console.log(person.name); // undefined - 'name' halka açık bir özellik değil // console.log(privateData.get(person)); // Erişilebilir, ancak doğrudan 'person.' aracılığıyla değil

Promise.allSettled Uygulaması

Promise.allSettled gibi davranan bir fonksiyon uygulayın.

Açıklama: Promise.allSettled bir dizi promise alır ve tek bir promise döndürür. Bu promise, tüm girdi promiseleri yerine getirildiğinde (ya yerine getirildi ya da reddedildi) yerine getirilir. Yerine getirme değeri, her bir promise in sonucunu açıklayan nesnelerden oluşan bir dizidir ({status: 'fulfilled', value: ...} veya {status: 'rejected', reason: ...}).

function myPromiseAllSettled(promises) { return new Promise((resolve) => { const numPromises = promises.length; const results = []; let settledCount = 0; if (numPromises === 0) { resolve([]); return; } promises.forEach((promise, index) => { Promise.resolve(promise) .then(value => { results[index] = { status: 'fulfilled', value: value }; }) .catch(reason => { results[index] = { status: 'rejected', reason: reason }; }) .finally(() => { settledCount++; if (settledCount === numPromises) { resolve(results); } }); }); }); } // Örnek: myPromiseAllSettled([Promise.resolve(1), Promise.reject('err')]) // -> [{status: 'fulfilled', value: 1}, {status: 'rejected', reason: 'err'}]

İki Sıralı Dizinin Medyanını Bul

Sırasıyla m ve n boyutlarında iki sıralı dizi nums1 ve nums2 verildiğinde, iki sıralı dizinin medyanını döndürün.

Açıklama: Bu, genellikle daha küçük dizi üzerinde ikili arama yaklaşımıyla çözülen zor bir problemdir. Amaç, her iki diziyi de öyle bölümlere ayırmaktır ki, sol taraftaki tüm elemanlar sağ taraftaki tüm elemanlardan küçük veya eşit olsun ve sol taraftaki eleman sayısı sağ taraftaki eleman sayısına eşit (veya bir fazla) olsun. Medyan daha sonra sınır elemanlarından hesaplanabilir.

function findMedianSortedArrays(nums1, nums2) { if (nums1.length > nums2.length) [nums1, nums2] = [nums2, nums1]; // nums1'in daha küçük olduğundan emin ol const m = nums1.length, n = nums2.length; let low = 0, high = m; while (low <= high) { const partitionX = Math.floor((low + high) / 2); const partitionY = Math.floor((m + n + 1) / 2) - partitionX; const maxX = (partitionX === 0) ? -Infinity : nums1[partitionX - 1]; const minX = (partitionX === m) ? Infinity : nums1[partitionX]; const maxY = (partitionY === 0) ? -Infinity : nums2[partitionY - 1]; const minY = (partitionY === n) ? Infinity : nums2[partitionY]; if (maxX <= minY && maxY <= minX) { if ((m + n) % 2 === 0) { return (Math.max(maxX, maxY) + Math.min(minX, minY)) / 2; } else { return Math.max(maxX, maxY); } } else if (maxX > minY) { high = partitionX - 1; } else { low = partitionX + 1; } } throw new Error('Girdi dizileri sıralı değil'); } console.log(findMedianSortedArrays([1, 3], [2])); // 2.0 console.log(findMedianSortedArrays([1, 2], [3, 4])); // 2.5

Sudoku Çözücü

Boş hücreleri doldurarak bir Sudoku bulmacasını çözen bir program yazın.

Açıklama: Geri izleme kullanın. Boş bir hücre bulun. Onu 1'den 9'a kadar sayılarla doldurmayı deneyin. Her sayı için, geçerli olup olmadığını (Sudoku kurallarını ihlal etmediğini) kontrol edin. Geçerliyse, özyinelemeli olarak çözücüyü çağırın. Eğer özyineleme doğru döndürürse, bir çözüm bulunmuştur. Aksi takdirde, geri izleyin (hücreyi sıfırlayın) ve bir sonraki sayıyı deneyin.

function solveSudoku(board) { function isValid(row, col, numStr) { for (let i = 0; i < 9; i++) { if (board[row][i] === numStr) return false; // Satırı kontrol et if (board[i][col] === numStr) return false; // Sütunu kontrol et const boxRow = 3 * Math.floor(row / 3) + Math.floor(i / 3); const boxCol = 3 * Math.floor(col / 3) + i % 3; if (board[boxRow][boxCol] === numStr) return false; // Kutuyu kontrol et } return true; } function backtrack() { for (let r = 0; r < 9; r++) { for (let c = 0; c < 9; c++) { if (board[r][c] === '.') { for (let n = 1; n <= 9; n++) { const numStr = String(n); if (isValid(r, c, numStr)) { board[r][c] = numStr; if (backtrack()) return true; board[r][c] = '.'; // Geri izle } } return false; // Geçerli sayı bulunamadı } } } return true; // Tahta çözüldü } backtrack(); return board; } // Örnek, boş hücreler için '.' ile 9x9 bir tahta gerektirir.

Temel Bir Middleware Kalıbı Uygula

Web framework lerinde sıklıkla görülen basit bir middleware kalıbı uygulayın.

Açıklama: Middleware fonksiyonları, son işleyiciye ulaşmadan önce bir isteği işler. Her middleware, isteği/yanıtı değiştirebilir veya kontrolü bir sonraki next middleware ye geçirebilir. Bir middleware fonksiyonları listesini yöneten ve bunları sırayla yürüten bir sınıf veya nesne oluşturun.

class App { constructor() { this.middlewares = []; } use(fn) { this.middlewares.push(fn); } handle(request) { let index = 0; const next = () => { if (index < this.middlewares.length) { const middleware = this.middlewares[index++]; middleware(request, next); } }; next(); } } const app = new App(); app.use((req, next) => { console.log('1: Günlükleme...'); req.logged = true; next(); }); app.use((req, next) => { console.log('2: Kimlik doğrulama...'); req.authed = true; next(); }); app.use((req, next) => { console.log('3: Son İşleyici:', req); }); app.handle({ data: 'some request' }); // 1: Günlükleme... // 2: Kimlik doğrulama... // 3: Son İşleyici: { data: 'some request', logged: true, authed: true }

Yönlendirilmiş Grafikte Döngü Algılama

Yönlendirilmiş bir grafiğin döngü içerip içermediğini belirlemek için bir fonksiyon yazın.

Açıklama: Derinlik Öncelikli Arama (DFS) kullanın. İki küme tutun: visiting (şu anda özyineleme yığınında olan düğümler) ve visited (tamamen keşfedilmiş düğümler). DFS sırasında visiting kümesinde bir düğümle karşılaşırsanız, bir geri kenar buldunuz demektir, bu da bir döngü olduğu anlamına gelir.

function hasCycleDirected(graph) { const visiting = new Set(); const visited = new Set(); const nodes = Object.keys(graph); function dfs(node) { visiting.add(node); for (const neighbor of graph[node]) { if (visiting.has(neighbor)) return true; // Döngü tespit edildi if (!visited.has(neighbor)) { if (dfs(neighbor)) return true; } } visiting.delete(node); visited.add(node); return false; } for (const node of nodes) { if (!visited.has(node)) { if (dfs(node)) return true; } } return false; } const cyclicGraph = { A: ['B'], B: ['C'], C: ['A'] }; const acyclicGraph = { A: ['B', 'C'], B: ['D'], C: ['E'], D: [], E: [] }; console.log(hasCycleDirected(cyclicGraph)); // true console.log(hasCycleDirected(acyclicGraph)); // false

Object.freeze Davranışını Uygula

Object.freeze i açıklayın ve (sığ) bir sürümünü uygulayın.

Açıklama: Object.freeze yeni özellikler eklemeyi, mevcut özellikleri kaldırmayı ve mevcut özellikleri veya bunların numaralandırılabilirliğini, yapılandırılabilirliğini veya yazılabilirliğini değiştirmeyi engeller. Bir nesneyi değişmez (sığ bir şekilde) yapar. Bunu Object.preventExtensions ve Object.defineProperty kullanarak mevcut özellikleri yazılamaz ve yapılandırılamaz hale getirerek uygulayabilirsiniz.

function myFreeze(obj) { Object.preventExtensions(obj); // Yeni özellikler eklemeyi engelle Object.keys(obj).forEach(key => { Object.defineProperty(obj, key, { writable: false, configurable: false }); }); return obj; } const obj = { a: 1, b: 2 }; myFreeze(obj); // obj.c = 3; // Sessizce başarısız olur (veya katı modda hata fırlatır) // delete obj.a; // Sessizce başarısız olur (veya katı modda hata fırlatır) // obj.a = 10; // Sessizce başarısız olur (veya katı modda hata fırlatır) console.log(obj); // { a: 1, b: 2 }

Düzgün Animasyon İçin requestAnimationFrame Kullanımı

requestAnimationFrame i açıklayın ve basit bir animasyon döngüsü için nasıl kullanılacağını gösterin.

Açıklama: requestAnimationFrame (rAF), tarayıcıya bir animasyon gerçekleştirmek istediğinizi söyler ve bir sonraki yeniden boyamadan önce bir animasyonu güncellemek için belirtilen bir fonksiyonu çağırmasını ister. Animasyonlar için setTimeout veya setInterval kullanmaktan daha verimli ve akıcıdır, çünkü tarayıcının yenileme hızıyla senkronize olur ve sekme görünür olmadığında duraklatılır.

// HTML: <div id='box' style='width: 50px; height: 50px; background: red; position: absolute; left: 0px;'></div> const box = document.getElementById('box'); let position = 0; let startTime = null; function animate(currentTime) { if (!startTime) startTime = currentTime; const elapsedTime = currentTime - startTime; // 2 saniyede 100 piksel hareket et (50 piksel/saniye) position = (elapsedTime / 2000) * 100; if (position < 200) { // 200 piksele ulaşana kadar animasyon yapmaya devam et box.style.left = position + 'px'; requestAnimationFrame(animate); } else { box.style.left = '200px'; } } // Animasyonu başlat // requestAnimationFrame(animate); // Tarayıcıda çalıştırmak için yorumu kaldırın console.log('Tarayıcı animasyonları için requestAnimationFrame kullanın.');

Array.prototype.some Uygulaması

Array.prototype.some un kendi sürümünüzü uygulayın.

Açıklama: some, dizideki en az bir elemanın sağlanan fonksiyon tarafından uygulanan testi geçip geçmediğini test eder. Geri çağırma true döndüren bir eleman bulursa true döndürür; aksi takdirde, false döndürür.

function mySome(arr, callback, thisArg) { for (let i = 0; i < arr.length; i++) { if (i in arr) { // Seyrek dizileri ele al if (callback.call(thisArg, arr[i], i, arr)) { return true; } } } return false; } const arr = [1, 2, 3, 4, 5]; const hasEven = mySome(arr, x => x % 2 === 0); console.log(hasEven); // true

Array.prototype.every Uygulaması

Array.prototype.every nin kendi sürümünüzü uygulayın.

Açıklama: every, dizideki tüm elemanların sağlanan fonksiyon tarafından uygulanan testi geçip geçmediğini test eder. Tüm elemanlar geçerse (veya dizi boşsa) true döndürür ve herhangi bir eleman başarısız olursa false döndürür.

function myEvery(arr, callback, thisArg) { for (let i = 0; i < arr.length; i++) { if (i in arr) { if (!callback.call(thisArg, arr[i], i, arr)) { return false; } } } return true; } const arr1 = [1, 30, 39, 29, 10, 13]; const isBelow40 = myEvery(arr1, x => x < 40); console.log(isBelow40); // true const arr2 = [1, 30, 39, 29, 10, 45]; const isBelow40_2 = myEvery(arr2, x => x < 40); console.log(isBelow40_2); // false

Array.prototype.findIndex Uygulaması

Array.prototype.findIndex in kendi sürümünüzü uygulayın.

Açıklama: findIndex, sağlanan test fonksiyonunu karşılayan dizideki ilk elemanın indeksini döndürür. Aksi takdirde, -1 döndürür, bu da hiçbir elemanın testi geçmediğini gösterir.

function myFindIndex(arr, callback, thisArg) { for (let i = 0; i < arr.length; i++) { if (i in arr) { if (callback.call(thisArg, arr[i], i, arr)) { return i; } } } return -1; } const arr = [5, 12, 8, 130, 44]; const isLargeNumber = (element) => element > 13; console.log(myFindIndex(arr, isLargeNumber)); // 3

Web İşçileri Nelerdir?

Web İşçilerinin ne olduğunu ve birincil kullanım durumlarını açıklayın.

Açıklama: Web İşçileri, web içeriğinin arka plan iş parçacıklarında betikleri çalıştırmasının bir yoludur. Ana kullanım durumu, uzun süreli veya yoğun işlem gerektiren görevleri ana iş parçacığından (kullanıcı arayüzü güncellemelerini ve kullanıcı etkileşimlerini yöneten) boşaltarak kullanıcı arayüzünün yanıt vermemesini veya 'donmasını' önlemektir. İşçiler, mesajlaşma yoluyla ana iş parçacığıyla iletişim kurar (postMessage ve onmessage).

// main.js /* if (window.Worker) { const myWorker = new Worker('worker.js'); myWorker.postMessage([5, 3]); // İşçiye veri gönder myWorker.onmessage = function(e) { console.log('İşçiden gelen sonuç:', e.data); } } else { console.log('Tarayıcınız Web İşçilerini desteklemiyor.'); } */ // worker.js /* self.onmessage = function(e) { console.log('Ana betikten mesaj alındı'); const result = e.data[0] * e.data[1]; console.log('Sonuç ana betiğe gönderiliyor'); self.postMessage(result); } */ console.log('Web İşçileri, betikleri arka plan iş parçacıklarında çalıştırır.');

Yolları Çöz

A-Z arasındaki harfleri içeren bir mesaj, A -> 1, B -> 2, ..., Z -> 26 eşlemesi kullanılarak sayılara kodlanabilir. Yalnızca rakamlar içeren bir s dizisi verildiğinde, onu çözmenin yollarının sayısını döndürün.

Açıklama: Dinamik programlama kullanın. dp[i] nin s[0...i-1] i çözme yollarının sayısı olduğunu varsayalım. dp[i], dp[i-1] e (s[i-1] geçerli bir 1 haneli kod ise) ve dp[i-2] ye (s[i-2...i-1] geçerli bir 2 haneli kod ise) bağlıdır.

function numDecodings(s) { if (!s || s[0] === '0') return 0; const n = s.length; const dp = new Array(n + 1).fill(0); dp[0] = 1; dp[1] = 1; for (let i = 2; i <= n; i++) { const oneDigit = parseInt(s.substring(i - 1, i)); const twoDigits = parseInt(s.substring(i - 2, i)); if (oneDigit >= 1) { dp[i] += dp[i - 1]; } if (twoDigits >= 10 && twoDigits <= 26) { dp[i] += dp[i - 2]; } } return dp[n]; } console.log(numDecodings('12')); // 2 ('AB' veya 'L') console.log(numDecodings('226')); // 3 ('BBF', 'BZ', 'VF') console.log(numDecodings('06')); // 0

Bitsel Toplama ( + kullanmadan)

  • operatörünü kullanmadan iki tamsayıyı toplayan bir fonksiyon yazın.

Açıklama: Bitsel operatörler kullanın. Toplam a ^ b (taşımasız toplam) olarak hesaplanabilir ve taşıma (a & b) << 1 olarak hesaplanabilir. Bu işlemi taşıma 0 olana kadar tekrarlayın.

function getSum(a, b) { while (b !== 0) { const carry = (a & b) << 1; // Taşımayı hesapla a = a ^ b; // Taşımadan toplamı hesapla b = carry; // Taşıma yeni 'b' olur } return a; } console.log(getSum(3, 5)); // 8 console.log(getSum(-2, 3)); // 1

Palindrom Kontrolü (Sayı)

Bir tamsayı x verildiğinde, x bir palindrom ise true, aksi takdirde false döndürün.

Açıklama: Negatif bir sayı palindrom değildir. Sayıyı bir dizeye dönüştürün ve dizenin bir palindrom olup olmadığını kontrol edin (ileri ve geri aynı okunuyor). Alternatif olarak, sayıyı matematiksel olarak ters çevirin ve karşılaştırın.

function isPalindromeNumber(x) { if (x < 0) return false; // Dize yaklaşımı // return String(x) === String(x).split('').reverse().join(''); // Matematiksel yaklaşım let original = x; let reversed = 0; while (x > 0) { reversed = reversed * 10 + (x % 10); x = Math.floor(x / 10); } return original === reversed; } console.log(isPalindromeNumber(121)); // true console.log(isPalindromeNumber(-121)); // false console.log(isPalindromeNumber(10)); // false

Fabrika Kalıbı

JavaScript te Fabrika tasarım kalıbını uygulayın.

Açıklama: Fabrika kalıbı, bir üst sınıfta nesneler oluşturmak için bir arayüz sağlar, ancak alt sınıfların oluşturulacak nesnelerin türünü değiştirmesine izin verir. Nesneleri kesin sınıfını belirtmeden oluşturmak için kullanışlıdır.

class Car { constructor(options) { this.type = 'Car'; this.doors = options.doors || 4; } } class Truck { constructor(options) { this.type = 'Truck'; this.bedSize = options.bedSize || 'long'; } } class VehicleFactory { createVehicle(options) { if (options.vehicleType === 'car') { return new Car(options); } else if (options.vehicleType === 'truck') { return new Truck(options); } else { throw new Error('Bilinmeyen araç tipi'); } } } const factory = new VehicleFactory(); const car = factory.createVehicle({ vehicleType: 'car', doors: 2 }); const truck = factory.createVehicle({ vehicleType: 'truck', bedSize: 'short' }); console.log(car); // Car { type: 'Car', doors: 2 } console.log(truck); // Truck { type: 'Truck', bedSize: 'short' }

Symbol i Açıkla ve Bir Kullanım Örneği Ver

JavaScript te Symbol ün ne olduğunu açıklayın ve 'özel' özellikler veya benzersiz nesne anahtarları oluşturma gibi bir kullanım örneği sağlayın.

Açıklama: Symbol, ES6 da tanıtılan ilkel bir veri türüdür. Örnekleri benzersiz ve değişmezdir. Genellikle farklı kütüphaneler arasındaki ad çakışmalarını önlemek veya sahte özel özellikler oluşturmak için nesne özellikleri için anahtar olarak kullanılırlar (gerçekten özel olmasalar da, tipik yineleme veya Object.keys aracılığıyla erişilemezler).

const _privateName = Symbol('name'); const _privateMethod = Symbol('greet'); class Person { constructor(name) { this[_privateName] = name; } [_privateMethod]() { console.log(`Merhaba, benim adım ${this[_privateName]}`); } introduce() { this[_privateMethod](); } } const p = new Person('Bob'); p.introduce(); // Merhaba, benim adım Bob console.log(Object.keys(p)); // [] - Semboller dahil edilmez console.log(p[_privateName]); // Bob (Sembole sahipseniz erişilebilir)

arguments ı Gerçek Bir Diziye Dönüştür

arguments nesnesini (ok fonksiyonu olmayan fonksiyonlarda kullanılabilir) gerçek bir JavaScript dizisine nasıl dönüştürebilirsiniz?

Açıklama: arguments nesnesi bir dizi gibi görünür ancak aslında değildir; map, filter vb. gibi yöntemleri yoktur. Onu aşağıdaki yollarla dönüştürebilirsiniz:

  1. Array.from(arguments) (ES6)
  2. [...arguments] (ES6 Yayma Sözdizimi)
  3. Array.prototype.slice.call(arguments) (Eski yöntem)
function sumAll() { // 1. Array.from const args1 = Array.from(arguments); console.log('Array.from kullanarak:', args1.reduce((a, b) => a + b, 0)); // 2. Yayma Sözdizimi const args2 = [...arguments]; console.log('Yayma kullanarak:', args2.reduce((a, b) => a + b, 0)); // 3. Slice const args3 = Array.prototype.slice.call(arguments); console.log('Slice kullanarak:', args3.reduce((a, b) => a + b, 0)); } sumAll(1, 2, 3, 4); // Array.from kullanarak: 10 // Yayma kullanarak: 10 // Slice kullanarak: 10