1. Алгоритмы сортировки
Пузырьковая сортировка в JavaScript:
function bubbleSort(arr) { for (let i = 0; i < arr.length; i++) { for (let j = 0; j < arr.length - i - 1; j++) { if (arr[j] > arr[j + 1]) { const temp = arr[j]; arr[j] = arr[j + 1]; arr[j + 1] = temp; } } } return arr; }
Сортировка слиянием в JavaScript:
function mergeSort(arr) { if (arr.length === 1) { return arr; } const mid = Math.floor(arr.length / 2); const left = arr.slice(0, mid); const right = arr.slice(mid); return merge(mergeSort(left), mergeSort(right)); } function merge(left, right) { const result = []; let i = 0; let j = 0; while (i < left.length && j < right.length) { if (left[i] < right[j]) { result.push(left[i++]); } else { result.push(right[j++]); } } return result.concat(left.slice(i)).concat(right.slice(j)); }
Быстрая сортировка в JavaScript:
function quickSort(arr, left = 0, right = arr.length - 1) { if (left < right) { const pivotIndex = partition(arr, left, right); quickSort(arr, left, pivotIndex - 1); quickSort(arr, pivotIndex + 1, right); } return arr; } function partition(arr, left, right) { const pivot = arr[right]; let i = left - 1; for (let j = left; j < right; j++) { if (arr[j] <= pivot) { i++; swap(arr, i, j); } } swap(arr, i + 1, right); return i + 1; } function swap(arr, i, j) { const temp = arr[i]; arr[i] = arr[j]; arr[j] = temp; }
Сортировка кучей в JavaScript:
function heapSort(arr) { buildMaxHeap(arr); for (let i = arr.length - 1; i >= 1; i--) { swap(arr, 0, i); heapify(arr, i, 0); } return arr; } function buildMaxHeap(arr) { const n = arr.length; for (let i = Math.floor(n / 2) - 1; i >= 0; i--) { heapify(arr, n, i); } } function heapify(arr, n, i) { let largest = i; const left = 2 * i + 1; const right = 2 * i + 2; if (left < n && arr[left] > arr[largest]) { largest = left; } if (right < n && arr[right] > arr[largest]) { largest = right; } if (largest !== i) { swap(arr, i, largest); heapify(arr, n, largest); } } function swap(arr, i, j) { const temp = arr[i]; arr[i] = arr[j]; arr[j] = temp; }
Важно отметить, что эти алгоритмы имеют разную временную и пространственную сложность, и некоторые из них могут лучше подходить для конкретных случаев использования, чем другие. При выборе алгоритма сортировки важно учитывать размер данных, желаемую временную сложность и желаемую пространственную сложность.
2. Алгоритм поиска
Вот пример бинарного поиска, поиска в ширину и поиска в глубину в JavaScript:
Двоичный поиск в JavaScript:
function binarySearch(arr, target) { let left = 0; let right = arr.length - 1; while (left <= right) { const mid = Math.floor((left + right) / 2); if (arr[mid] === target) { return mid; } else if (arr[mid] < target) { left = mid + 1; } else { right = mid - 1; } } return -1; }
Первый в ширину в JavaScript:
// Breadth-First Search function breadthFirstSearch(root, target) { const queue = [root]; while (queue.length > 0) { const node = queue.shift(); if (node.value === target) { return node; } queue.push(...node.children); } return null; }
Сначала в глубину в JavaScript:
// Depth-First Search function depthFirstSearch(root, target) { if (root.value === target) { return root; } for (const child of root.children) { const result = depthFirstSearch(child, target); if (result) { return result; } } return null; }
В приведенном выше примере binarySearch
принимает массив arr
и целевое значение и возвращает индекс целевого значения в массиве, если оно существует, или -1, если оно не существует.
breadthFirstSearch
берет дерево, представленное корневым узлом и целевым значением, и возвращает узел в дереве с целевым значением, если он существует, или null, если он не существует.
depthFirstSearch
берет дерево, представленное корневым узлом и целевым значением, и возвращает узел в дереве с целевым значением, если он существует, или null, если он не существует.
а. Пример использования функции binarySearch
в JavaScript:
const arr = [1, 2, 3, 4, 5, 6, 7, 8, 9]; const target = 6; const result = binarySearch(arr, target); if (result === -1) { console.log(`${target} not found in the array`); } else { console.log(`${target} found at index ${result}`); }
В этом примере функция binarySearch
вызывается с массивом arr
и целевым значением 6
. Функция возвращает 5
, который является индексом 6
в массиве. Затем код проверяет результат и выводит соответствующее сообщение на консоль.
б. Пример использования функции breadthFirstSearch
в JavaScript:
const tree = { value: 1, children: [ { value: 2, children: [ { value: 4, children: [] }, { value: 5, children: [] }, ] }, { value: 3, children: [ { value: 6, children: [] }, { value: 7, children: [] }, ] }, ] }; const target = 5; const result = breadthFirstSearch(tree, target); if (!result) { console.log(`${target} not found in the tree`); } else { console.log(`${target} found with value ${result.value}`); }
В этом примере функция breadthFirstSearch
вызывается с деревом, представленным корневым узлом, и целевым значением 5
. Функция возвращает узел в дереве со значением 5
, который является дочерним узлом корневого узла. Затем код проверяет результат и выводит соответствующее сообщение на консоль.
в. Пример использования функции depthFirstSearch
в JavaScript:
const tree = { value: 1, children: [ { value: 2, children: [ { value: 4, children: [] }, { value: 5, children: [] }, ] }, { value: 3, children: [ { value: 6, children: [] }, { value: 7, children: [] }, ] }, ] }; const target = 5; const result = depthFirstSearch(tree, target); if (!result) { console.log(`${target} not found in the tree`); } else { console.log(`${target} found with value ${result.value}`); }
В этом примере функция depthFirstSearch
вызывается с деревом, представленным корневым узлом, и целевым значением 5
. Функция возвращает узел в дереве со значением 5
, который является дочерним узлом корневого узла. Затем код проверяет результат и выводит соответствующее сообщение на консоль.
3. Динамическое программирование
Динамическое программирование — это метод решения проблем путем их разбиения на более мелкие подзадачи и повторного использования решений этих подзадач для поиска решения исходной проблемы. Ключевая идея динамического программирования состоит в том, чтобы избежать избыточных вычислений, запоминая промежуточные результаты и повторно используя их по мере необходимости.
Вот пример того, как использовать динамическое программирование в JavaScript для решения задачи нахождения n-го числа Фибоначчи:
function fibonacci(n, memo = {}) { if (n <= 0) return 0; if (n === 1) return 1; if (memo[n]) return memo[n]; memo[n] = fibonacci(n - 1, memo) + fibonacci(n - 2, memo); return memo[n]; } console.log(fibonacci(10));
В этом примере функция fibonacci
использует технику запоминания для сохранения промежуточных результатов в объекте, переданном в качестве аргумента. Это позволяет функции повторно использовать решения подзадач, улучшая временную сложность вычислений. Функция возвращает n-е число Фибоначчи, доступ к которому можно получить, вызвав fibonacci(10)
в этом примере.
4. Алгоритм рекурсии
Рекурсия — это метод, при котором функция вызывает саму себя, чтобы решить проблему, разделив ее на более мелкие подзадачи. Подзадачи решаются рекурсивно, а решения подзадач объединяются, чтобы найти решение исходной проблемы. Рекурсия полезна для решения проблем с рекурсивной структурой, когда решение проблемы может быть выражено в терминах решений более мелких экземпляров той же проблемы.
Вот пример использования рекурсии в JavaScript для вычисления факториала заданного числа:
function factorial(n) { if (n === 1) return 1; return n * factorial(n - 1); } console.log(factorial(5));
В этом примере функция factorial
вызывает себя рекурсивно, пока не будет достигнут базовый случай, где n === 1
. Функция возвращает произведение n
и факториала n - 1
, что является результатом рекурсивного вызова. Решение исходной задачи получается путем объединения решений подзадач таким образом. Факториал 5
можно вычислить, вызвав factorial(5)
, который вернет 120
.
5. Алгоритм «разделяй и властвуй»
Разделяй и властвуй — это алгоритмический метод, при котором проблема делится на более мелкие подзадачи, которые легче решить. Затем решения подзадач объединяются, чтобы найти решение исходной проблемы. Подход «разделяй и властвуй» полезен для решения проблем, которые можно разбить на более мелкие подзадачи, похожие на исходную проблему.
Вот пример того, как использовать разделяй и властвуй в JavaScript, чтобы найти максимальное число в массиве:
function max(array, start, end) { if (start === end) return array[start]; const mid = Math.floor((start + end) / 2); const leftMax = max(array, start, mid); const rightMax = max(array, mid + 1, end); return Math.max(leftMax, rightMax); } const array = [1, 2, 3, 4, 5]; console.log(max(array, 0, array.length - 1));
В этом примере функция max
использует подход «разделяй и властвуй», чтобы найти максимальное число в массиве. Массив делится на две половины, и максимальное число в каждой половине находится путем рекурсивного вызова функции max
. Конечным результатом является максимальное из двух результатов, то есть максимальное число во всем массиве. Вызов max(array, 0, array.length - 1)
вернет 5
, что является максимальным числом в массиве.
6. Техника хеширования
Хэширование — это метод, используемый в информатике для сопоставления данных произвольного размера с данными фиксированного размера. Хэш-функция принимает входные данные, известные как сообщение или прообраз, и возвращает строку символов фиксированного размера, известную как хэш или дайджест. Один и тот же ввод всегда будет давать один и тот же хэш, но даже небольшое изменение ввода приведет к совершенно другому хешу.
В JavaScript хэши можно генерировать с помощью модуля crypto
, обеспечивающего криптографическую функциональность. Вот пример использования модуля crypto
для генерации хэша SHA-256:
const crypto = require('crypto'); function hash(message) { return crypto.createHash('sha256') .update(message) .digest('hex'); } const message = 'Hello, world!'; console.log(hash(message));
В этом примере функция hash
использует модуль crypto
для создания хэша SHA-256 входного сообщения. Вызов hash(message)
вернет строку шестнадцатеричных символов, представляющую хэш входного сообщения. Один и тот же ввод всегда будет давать один и тот же хэш, поэтому этот метод можно использовать для проверки целостности данных.