-
Notifications
You must be signed in to change notification settings - Fork 5
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
33 changed files
with
530 additions
and
35 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
<!DOCTYPE html> | ||
<html> | ||
<head> | ||
<style> | ||
.curved-shape { | ||
width: 200px; | ||
height: 200px; | ||
background-color: #3498db; | ||
clip-path: path('M 0,0 Q 75,50 150,0'); | ||
} | ||
</style> | ||
</head> | ||
<body> | ||
|
||
<div class="curved-shape"></div> | ||
|
||
</body> | ||
</html> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,29 @@ | ||
/** | ||
* 回溯算法 -组合问题 | ||
* 回溯算法是一种通过尝试所有可能的路径来解决问题的算法策略。在遇到不可行的路径时, | ||
* 它会回退到上一个决策点,尝试其他路径,直到找到解决方案或遍历完所有可能的路径。 | ||
*/ | ||
function combine(n, k) { | ||
const result = []; | ||
const path = []; | ||
|
||
function backtrack(start) { | ||
if (path.length === k) { | ||
result.push([...path]); | ||
return; | ||
} | ||
for (let i = start; i <= n; i++) { | ||
path.push(i); | ||
backtrack(i + 1); | ||
path.pop(); | ||
} | ||
} | ||
|
||
backtrack(1); | ||
return result; | ||
} | ||
|
||
// 测试 | ||
const n = 4; | ||
const k = 2; | ||
console.log(combine(n, k)); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,33 @@ | ||
/** | ||
* 回溯算法 - 全排列 | ||
* 回溯算法是一种通过尝试所有可能的路径来解决问题的算法策略。在遇到不可行的路径时, | ||
* 它会回退到上一个决策点,尝试其他路径,直到找到解决方案或遍历完所有可能的路径。 | ||
* 给定一个不包含重复数字的数组,返回所有可能的全排列。 | ||
*/ | ||
function permute(nums) { | ||
const result = []; | ||
const used = new Array(nums.length).fill(false); | ||
const path = []; | ||
|
||
function backtrack() { | ||
if (path.length === nums.length) { | ||
result.push([...path]); | ||
return; | ||
} | ||
for (let i = 0; i < nums.length; i++) { | ||
if (used[i]) continue; | ||
path.push(nums[i]); | ||
used[i] = true; | ||
backtrack(); | ||
path.pop(); | ||
used[i] = false; | ||
} | ||
} | ||
|
||
backtrack(); | ||
return result; | ||
} | ||
|
||
// 测试 | ||
const nums = [1, 2, 3]; | ||
console.log(permute(nums)); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,61 @@ | ||
/** | ||
* 回溯算法 - 解数独 | ||
* 回溯算法是一种通过尝试所有可能的路径来解决问题的算法策略。在遇到不可行的路径时, | ||
* 它会回退到上一个决策点,尝试其他路径,直到找到解决方案或遍历完所有可能的路径。 | ||
*/ | ||
function solveSudoku(board) { | ||
function isValid(row, col, num) { | ||
// 检查行 | ||
for (let i = 0; i < 9; i++) { | ||
if (board[row][i] === num) return false; | ||
} | ||
// 检查列 | ||
for (let i = 0; i < 9; i++) { | ||
if (board[i][col] === num) return false; | ||
} | ||
// 检查 3x3 子棋盘 | ||
const startRow = Math.floor(row / 3) * 3; | ||
const startCol = Math.floor(col / 3) * 3; | ||
for (let i = startRow; i < startRow + 3; i++) { | ||
for (let j = startCol; j < startCol + 3; j++) { | ||
if (board[i][j] === num) return false; | ||
} | ||
} | ||
return true; | ||
} | ||
|
||
function backtrack() { | ||
for (let i = 0; i < 9; i++) { | ||
for (let j = 0; j < 9; j++) { | ||
if (board[i][j] === '.') { | ||
for (let num = 1; num <= 9; num++) { | ||
if (isValid(i, j, num)) { | ||
board[i][j] = num.toString(); | ||
if (backtrack()) return true; | ||
board[i][j] = '.'; | ||
} | ||
} | ||
return false; | ||
} | ||
} | ||
} | ||
return true; | ||
} | ||
|
||
backtrack(); | ||
return board; | ||
} | ||
|
||
// 测试 | ||
const board = [ | ||
['5', '3', '.', '.', '7', '.', '.', '.', '.'], | ||
['6', '.', '.', '1', '9', '5', '.', '.', '.'], | ||
['.', '9', '8', '.', '.', '.', '.', '6', '.'], | ||
['8', '.', '.', '.', '6', '.', '.', '.', '3'], | ||
['4', '.', '.', '8', '.', '3', '.', '.', '1'], | ||
['7', '.', '.', '.', '2', '.', '.', '.', '6'], | ||
['.', '6', '.', '.', '.', '.', '2', '8', '.'], | ||
['.', '.', '.', '4', '1', '9', '.', '.', '5'], | ||
['.', '.', '.', '.', '8', '.', '.', '7', '9'], | ||
]; | ||
console.log(solveSudoku(board)); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,27 @@ | ||
/** | ||
* 分治算法(Divide and Conquer Algorithm)是一种常用的算法策略, | ||
* 它将一个复杂的问题分解成多个规模较小、相互独立且形式相同的子问题, | ||
* 然后分别解决这些子问题,最后将子问题的解合并起来得到原问题的解。 | ||
* | ||
* 给定一个整数数组 nums,找到一个具有最大和的连续子数组(子数组最少包含一个元素),返回其最大和。 | ||
*/ | ||
|
||
function maxSubArray(nums) { | ||
if (nums.length === 1) { | ||
return nums[0]; | ||
} | ||
|
||
let maxEndingHere = nums[0]; | ||
let maxSoFar = nums[0]; | ||
|
||
for (let i = 1; i < nums.length; i++) { | ||
maxEndingHere = Math.max(nums[i], maxEndingHere + nums[i]); | ||
maxSoFar = Math.max(maxSoFar, maxEndingHere); | ||
} | ||
|
||
return maxSoFar; | ||
} | ||
|
||
// 测试 | ||
const nums = [-2, 1, -3, 4, -1, 2, 3, -5, 4]; | ||
console.log(maxSubArray(nums)); // 输出 6 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,47 @@ | ||
/** | ||
* 分治算法(Divide and Conquer Algorithm)是一种常用的算法策略, | ||
* 它将一个复杂的问题分解成多个规模较小、相互独立且形式相同的子问题, | ||
* 然后分别解决这些子问题,最后将子问题的解合并起来得到原问题的解。 | ||
* | ||
* 归并排序是一种典型的分治算法,它将一个数组分成两个子数组,分别对这两个子数组进行排序,然后将排好序的子数组合并成一个有序的数组。 | ||
*/ | ||
|
||
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); | ||
|
||
// 递归排序子数组 | ||
const sortedLeft = mergeSort(left); | ||
const sortedRight = mergeSort(right); | ||
|
||
// 合并两个有序子数组 | ||
return merge(sortedLeft, sortedRight); | ||
} | ||
|
||
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)); | ||
} | ||
|
||
// 测试 | ||
const array = [38, 27, 43, 3, 9, 82, 10]; | ||
console.log(mergeSort(array)); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,35 @@ | ||
/** | ||
* 分治算法(Divide and Conquer Algorithm)是一种常用的算法策略, | ||
* 它将一个复杂的问题分解成多个规模较小、相互独立且形式相同的子问题, | ||
* 然后分别解决这些子问题,最后将子问题的解合并起来得到原问题的解。 | ||
* | ||
* 快速排序也是基于分治思想,通过选择一个基准元素,将数组分为两部分,使得左边部分的元素都小于等于基准元素,右边部分的元素都大于等于基准元素,然后分别对左右两部分进行排序。 | ||
*/ | ||
|
||
function quickSort(arr) { | ||
if (arr.length <= 1) { | ||
return arr; | ||
} | ||
|
||
// 选择基准元素 | ||
const pivot = arr[Math.floor(arr.length / 2)]; | ||
const left = []; | ||
const right = []; | ||
const equal = []; | ||
|
||
for (let num of arr) { | ||
if (num < pivot) { | ||
left.push(num); | ||
} else if (num > pivot) { | ||
right.push(num); | ||
} else { | ||
equal.push(num); | ||
} | ||
} | ||
|
||
return [...quickSort(left),...equal,...quickSort(right)]; | ||
} | ||
|
||
// 测试 | ||
const array2 = [38, 27, 43, 3, 9, 82, 10]; | ||
console.log(quickSort(array2)); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
/** | ||
* 动态规划(Dynamic Programming,DP)是一种通过把原问题分解为相对简单的子问题, | ||
* 并保存子问题的解来避免重复计算,从而解决复杂问题的算法策略。 | ||
*/ | ||
|
||
|
||
function climbStairs(n) { | ||
if (n <= 2) { | ||
return n; | ||
} | ||
let dp = new Array(n + 1); | ||
dp[1] = 1; | ||
dp[2] = 2; | ||
for (let i = 3; i <= n; i++) { | ||
dp[i] = dp[i - 1] + dp[i - 2]; | ||
} | ||
return dp[n]; | ||
} | ||
|
||
// 测试 | ||
console.log(climbStairs(5)); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,23 @@ | ||
/** | ||
* 动态规划(Dynamic Programming,DP)是一种通过把原问题分解为相对简单的子问题, | ||
* 并保存子问题的解来避免重复计算,从而解决复杂问题的算法策略。 | ||
* | ||
* 0 - 1 背包问题:有 n 个物品,每个物品有重量 weights 和价值 values,背包的容量为 capacity。每个物品只能使用一次,求能装入背包的最大价值。 | ||
*/ | ||
|
||
|
||
function fibonacci(n) { | ||
if (n <= 1) { | ||
return n; | ||
} | ||
let dp = new Array(n + 1); | ||
dp[0] = 0; | ||
dp[1] = 1; | ||
for (let i = 2; i <= n; i++) { | ||
dp[i] = dp[i - 1] + dp[i - 2]; | ||
} | ||
return dp[n]; | ||
} | ||
|
||
// 测试 | ||
console.log(fibonacci(10)); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,28 @@ | ||
/** | ||
* 动态规划(Dynamic Programming,DP)是一种通过把原问题分解为相对简单的子问题, | ||
* 并保存子问题的解来避免重复计算,从而解决复杂问题的算法策略。 | ||
* | ||
* 假设你正在爬楼梯。需要 n 阶你才能到达楼顶。每次你可以爬 1 或 2 个台阶。你有多少种不同的方法可以爬到楼顶呢? | ||
*/ | ||
|
||
function knapsack(capacity, weights, values) { | ||
let n = weights.length; | ||
let dp = new Array(n + 1).fill(0).map(() => new Array(capacity + 1).fill(0)); | ||
|
||
for (let i = 1; i <= n; i++) { | ||
for (let w = 0; w <= capacity; w++) { | ||
if (weights[i - 1] > w) { | ||
dp[i][w] = dp[i - 1][w]; | ||
} else { | ||
dp[i][w] = Math.max(dp[i - 1][w], dp[i - 1][w - weights[i - 1]] + values[i - 1]); | ||
} | ||
} | ||
} | ||
return dp[n][capacity]; | ||
} | ||
|
||
// 测试 | ||
let capacity = 5; | ||
let weights = [2, 3, 4, 5]; | ||
let values = [3, 4, 5, 6]; | ||
console.log(knapsack(capacity, weights, values)); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,29 @@ | ||
/** | ||
* 贪心算法是一种在每一步选择中都采取当前状态下的最优决策,从而希望最终得到全局最优解的算法策略。 | ||
* 虽然贪心算法并不总是能得到全局最优解,但在许多问题上它可以提供高效且近似最优的解决方案。 | ||
* 假设有一组活动,每个活动都有开始时间和结束时间,你需要选择尽可能多的活动,使得这些活动之间没有时间冲突。 | ||
*/ | ||
|
||
function activitySelection(activities) { | ||
activities.sort((a, b) => a.end - b.end); | ||
let selected = []; | ||
let lastEnd = -1; | ||
for (let activity of activities) { | ||
if (activity.start >= lastEnd) { | ||
selected.push(activity); | ||
lastEnd = activity.end; | ||
} | ||
} | ||
return selected; | ||
} | ||
|
||
// 测试 | ||
const activities = [ | ||
{ start: 1, end: 3 }, | ||
{ start: 2, end: 4 }, | ||
{ start: 3, end: 5 }, | ||
{ start: 5, end: 7 }, | ||
{ start: 3, end: 8 } | ||
]; | ||
const result = activitySelection(activities); | ||
console.log(result); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
/** | ||
* 贪心算法是一种在每一步选择中都采取当前状态下的最优决策,从而希望最终得到全局最优解的算法策略。 | ||
* 虽然贪心算法并不总是能得到全局最优解,但在许多问题上它可以提供高效且近似最优的解决方案。 | ||
* 假设你有无限数量的硬币,硬币面额为 [1, 5, 10, 25](美分),要找给顾客 amount 美分,求最少需要多少枚硬币。 | ||
*/ | ||
|
||
function coinChange(amount) { | ||
const coins = [25, 10, 5, 1]; | ||
let count = 0; | ||
for (let coin of coins) { | ||
count += Math.floor(amount / coin); | ||
amount %= coin; | ||
} | ||
return count; | ||
} | ||
|
||
// 测试 | ||
const amount = 63; | ||
console.log(coinChange(amount)); // 输出 6 |
Oops, something went wrong.