軟體工程師職涯升級計畫啟動!立即預約職涯諮詢、履歷健檢或模擬面試👈,為您的加薪做好準備!
這篇文章整理了 JavaScript 中常見的演算法與資料結構題型,包括排列組合、排序、搜尋、樹與鏈結串列等,並為每段程式碼附上簡短說明,幫助你快速理解其應用情境與邏輯。無論你正在準備前端、全端或軟體工程師面試,這是一份可以在面試前快速翻閱的筆記,幫助你臨陣不亂,打好演算法基礎!
1. 排列(Permutations)
說明: 產生所有可能的排列組合,常見於排列問題、DFS 樹狀結構遍歷。
javascript
複製編輯var permute = function(nums) {
const result = [];
const backtrack = (nums, path) => {
if (nums.length === 0) {
result.push(path);
return;
}
for (let i = 0; i < nums.length; i++) {
backtrack([...nums.slice(0, i), ...nums.slice(i + 1)], [...path, nums[i]]);
}
};
backtrack(nums, []);
return result;
};
2. 組合(Combinations)
說明: 從 n 個數中選出 k 個不重複的組合,常用於組合問題或 DFS 剪枝題。
javascript
複製編輯var combine = function(n, k) {
const result = [];
backtrack(n, k, 1, [], result);
return result;
};
function backtrack(n, k, start, combination, result) {
if (combination.length === k) {
result.push([...combination]);
return;
}
for (let i = start; i <= n; i++) {
combination.push(i);
backtrack(n, k, i + 1, combination, result);
combination.pop();
}
}
3. 二分搜尋(Binary Search)
說明: 適用於有序陣列,以對半方式高效搜尋目標值,時間複雜度 O(log n)。
javascript
複製編輯var search = function(nums, target) {
let left = 0, right = nums.length - 1;
while (right >= left) {
let mid = Math.floor((left + right) / 2);
if (target > nums[mid]) {
left = mid + 1;
} else if (target < nums[mid]) {
right = mid - 1;
} else {
return mid;
}
}
return -1;
};
4. 合併排序(Merge Sort)
說明: 經典的排序演算法,使用「分而治之」策略,穩定排序,時間複雜度 O(n log n)。
javascript
複製編輯function merge(left, right) {
let arr = [];
while (left.length && right.length) {
if (left[0] < right[0]) {
arr.push(left.shift());
} else {
arr.push(right.shift());
}
}
return [...arr, ...left, ...right];
}
var sortArray = function(nums) {
if (nums.length < 2) return nums;
const half = Math.floor(nums.length / 2);
const left = nums.splice(0, half);
return merge(sortArray(left), sortArray(nums));
};
5. 快速排序(Quick Sort)
說明: 常用的原地排序方法,透過選定 pivot 分區再遞迴處理,平均時間複雜度 O(n log n)。
javascript
複製編輯var sortArray = function(nums) {
return quickSort(nums);
};
function pivot(arr, start = 0, end = arr.length - 1) {
function swap(array, i, j) {
[array[i], array[j]] = [array[j], array[i]];
}
let pivot = arr[start];
let swapIdx = start;
for (let i = start + 1; i <= end; i++) {
if (arr[i] < pivot) {
swapIdx++;
swap(arr, swapIdx, i);
}
}
swap(arr, start, swapIdx);
return swapIdx;
}
function quickSort(arr, left = 0, right = arr.length - 1) {
if (left < right) {
let pivotIndex = pivot(arr, left, right);
quickSort(arr, left, pivotIndex - 1);
quickSort(arr, pivotIndex + 1, right);
}
return arr;
}
6. 快速選擇(Quick Select)
說明: 找出第 k 小元素的高效演算法,類似 Quick Sort,但只處理一側,時間複雜度平均為 O(n)。
javascript
複製編輯function quickSelect(arr, left, right, k) {
if (left === right) return arr[left];
let pivotIndex = partition(arr, left, right);
if (k === pivotIndex) {
return arr[k];
} else if (k < pivotIndex) {
return quickSelect(arr, left, pivotIndex - 1, k);
} else {
return quickSelect(arr, pivotIndex + 1, right, k);
}
}
function partition(arr, left, right) {
let pivot = arr[right];
let i = left;
for (let j = left; j < right; j++) {
if (arr[j] <= pivot) {
[arr[i], arr[j]] = [arr[j], arr[i]];
i++;
}
}
[arr[i], arr[right]] = [arr[right], arr[i]];
return i;
}
// 使用範例
const arr = [3, 2, 1, 5, 4];
const k = 2;
console.log(quickSelect(arr, 0, arr.length - 1, k)); // 輸出 3
7. 二元樹中序遍歷(Inorder Traversal)
說明: 以「左 → 根 → 右」順序遍歷樹,常見於 BST 中可得到排序結果。
javascript
複製編輯var inorderTraversal = function(root) {
if (!root) return [];
return traversal(root, []);
};
function traversal(node, result) {
if (!node) return;
traversal(node.left, result);
result.push(node.val);
traversal(node.right, result);
return result;
}
8. 廣度優先搜尋(BFS)
說明: 一層一層遍歷樹的節點,常用於圖的最短路徑或層序遍歷。
javascript
複製編輯let queue = [root], ans = [];
while (queue.length > 0) {
let qlen = queue.length, row = [];
for (let i = 0; i < qlen; i++) {
let curr = queue.shift();
row.push(curr.val);
if (curr.left) queue.push(curr.left);
if (curr.right) queue.push(curr.right);
}
ans.push(row);
}
return ans;
9. 反轉鏈結串列(Reverse Linked List)
說明: 反轉單向鏈結串列的指向方向,是常見的基礎操作。
javascript
複製編輯let prev = null, curr = head;
while (curr) {
let nextTemp = curr.next;
curr.next = prev;
prev = curr;
curr = nextTemp;
}
return prev;
10. 樹節點類別範例(Tree Node Class)
說明: 建立一個簡單的多叉樹節點結構,可擴展用於樹建構、遍歷等應用。
javascript
複製編輯class Node {
constructor(key, value = key, parent = null) {
this.key = key;
this.value = value;
this.parent = parent;
this.children = [];
}
}
📌 總結
這些演算法是前端與全端開發者在面試時最常遇到的題型。熟悉它們的實作與原理,不僅能加快解題速度,也有助於寫出更具可讀性與效率的程式。