mirror of
				https://github.com/krahets/hello-algo.git
				synced 2025-11-04 14:18:20 +08:00 
			
		
		
		
	Fix the content
This commit is contained in:
		@ -14,7 +14,7 @@ int coinChangeGreedy(vector<int> &coins, int amt) {
 | 
				
			|||||||
    // 循环进行贪心选择,直到无剩余金额
 | 
					    // 循环进行贪心选择,直到无剩余金额
 | 
				
			||||||
    while (amt > 0) {
 | 
					    while (amt > 0) {
 | 
				
			||||||
        // 找到小于且最接近剩余金额的硬币
 | 
					        // 找到小于且最接近剩余金额的硬币
 | 
				
			||||||
        while (coins[i] > amt) {
 | 
					        while (i > 0 && coins[i] > amt) {
 | 
				
			||||||
            i--;
 | 
					            i--;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        // 选择 coins[i]
 | 
					        // 选择 coins[i]
 | 
				
			||||||
 | 
				
			|||||||
@ -15,7 +15,7 @@ public class coin_change_greedy {
 | 
				
			|||||||
        // 循环进行贪心选择,直到无剩余金额
 | 
					        // 循环进行贪心选择,直到无剩余金额
 | 
				
			||||||
        while (amt > 0) {
 | 
					        while (amt > 0) {
 | 
				
			||||||
            // 找到小于且最接近剩余金额的硬币
 | 
					            // 找到小于且最接近剩余金额的硬币
 | 
				
			||||||
            while (coins[i] > amt) {
 | 
					            while (i > 0 && coins[i] > amt) {
 | 
				
			||||||
                i--;
 | 
					                i--;
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
            // 选择 coins[i]
 | 
					            // 选择 coins[i]
 | 
				
			||||||
 | 
				
			|||||||
@ -12,7 +12,7 @@ func coinChangeGreedy(coins []int, amt int) int {
 | 
				
			|||||||
	// 循环进行贪心选择,直到无剩余金额
 | 
						// 循环进行贪心选择,直到无剩余金额
 | 
				
			||||||
	for amt > 0 {
 | 
						for amt > 0 {
 | 
				
			||||||
		// 找到小于且最接近剩余金额的硬币
 | 
							// 找到小于且最接近剩余金额的硬币
 | 
				
			||||||
		for coins[i] > amt {
 | 
							for i > 0 && coins[i] > amt {
 | 
				
			||||||
			i--
 | 
								i--
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		// 选择 coins[i]
 | 
							// 选择 coins[i]
 | 
				
			||||||
 | 
				
			|||||||
@ -17,7 +17,7 @@ public class coin_change_greedy {
 | 
				
			|||||||
        // 循环进行贪心选择,直到无剩余金额
 | 
					        // 循环进行贪心选择,直到无剩余金额
 | 
				
			||||||
        while (amt > 0) {
 | 
					        while (amt > 0) {
 | 
				
			||||||
            // 找到小于且最接近剩余金额的硬币
 | 
					            // 找到小于且最接近剩余金额的硬币
 | 
				
			||||||
            while (coins[i] > amt) {
 | 
					            while (i > 0 && coins[i] > amt) {
 | 
				
			||||||
                i--;
 | 
					                i--;
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
            // 选择 coins[i]
 | 
					            // 选择 coins[i]
 | 
				
			||||||
 | 
				
			|||||||
@ -15,14 +15,14 @@ public class top_k {
 | 
				
			|||||||
        Queue<Integer> heap = new PriorityQueue<Integer>();
 | 
					        Queue<Integer> heap = new PriorityQueue<Integer>();
 | 
				
			||||||
        // 将数组的前 k 个元素入堆
 | 
					        // 将数组的前 k 个元素入堆
 | 
				
			||||||
        for (int i = 0; i < k; i++) {
 | 
					        for (int i = 0; i < k; i++) {
 | 
				
			||||||
            heap.add(nums[i]);
 | 
					            heap.offer(nums[i]);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        // 从第 k+1 个元素开始,保持堆的长度为 k
 | 
					        // 从第 k+1 个元素开始,保持堆的长度为 k
 | 
				
			||||||
        for (int i = k; i < nums.length; i++) {
 | 
					        for (int i = k; i < nums.length; i++) {
 | 
				
			||||||
            // 若当前元素大于堆顶元素,则将堆顶元素出堆、当前元素入堆
 | 
					            // 若当前元素大于堆顶元素,则将堆顶元素出堆、当前元素入堆
 | 
				
			||||||
            if (nums[i] > heap.peek()) {
 | 
					            if (nums[i] > heap.peek()) {
 | 
				
			||||||
                heap.poll();
 | 
					                heap.poll();
 | 
				
			||||||
                heap.add(nums[i]);
 | 
					                heap.offer(nums[i]);
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        return heap;
 | 
					        return heap;
 | 
				
			||||||
 | 
				
			|||||||
@ -13,7 +13,7 @@ def coin_change_greedy(coins: list[int], amt: int) -> int:
 | 
				
			|||||||
    # 循环进行贪心选择,直到无剩余金额
 | 
					    # 循环进行贪心选择,直到无剩余金额
 | 
				
			||||||
    while amt > 0:
 | 
					    while amt > 0:
 | 
				
			||||||
        # 找到小于且最接近剩余金额的硬币
 | 
					        # 找到小于且最接近剩余金额的硬币
 | 
				
			||||||
        while coins[i] > amt:
 | 
					        while i > 0 and coins[i] > amt:
 | 
				
			||||||
            i -= 1
 | 
					            i -= 1
 | 
				
			||||||
        # 选择 coins[i]
 | 
					        # 选择 coins[i]
 | 
				
			||||||
        amt -= coins[i]
 | 
					        amt -= coins[i]
 | 
				
			||||||
 | 
				
			|||||||
@ -12,7 +12,7 @@ fn coin_change_greedy(coins: &[i32], mut amt: i32) -> i32 {
 | 
				
			|||||||
    // 循环进行贪心选择,直到无剩余金额
 | 
					    // 循环进行贪心选择,直到无剩余金额
 | 
				
			||||||
    while amt > 0 {
 | 
					    while amt > 0 {
 | 
				
			||||||
        // 找到小于且最接近剩余金额的硬币
 | 
					        // 找到小于且最接近剩余金额的硬币
 | 
				
			||||||
        while coins[i] > amt {
 | 
					        while i > 0 && coins[i] > amt {
 | 
				
			||||||
            i -= 1;
 | 
					            i -= 1;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        // 选择 coins[i]
 | 
					        // 选择 coins[i]
 | 
				
			||||||
 | 
				
			|||||||
@ -1,7 +1,5 @@
 | 
				
			|||||||
# 算法效率评估
 | 
					# 算法效率评估
 | 
				
			||||||
 | 
					
 | 
				
			||||||
## 算法评价维度
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
在算法设计中,我们先后追求以下两个层面的目标:
 | 
					在算法设计中,我们先后追求以下两个层面的目标:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
1. **找到问题解法**:算法需要在规定的输入范围内,可靠地求得问题的正确解。
 | 
					1. **找到问题解法**:算法需要在规定的输入范围内,可靠地求得问题的正确解。
 | 
				
			||||||
@ -14,9 +12,9 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
简而言之,**我们的目标是设计“既快又省”的数据结构与算法**。而有效地评估算法效率至关重要,因为只有了解评价标准,我们才能对比分析各种算法,从而指导算法设计与优化过程。
 | 
					简而言之,**我们的目标是设计“既快又省”的数据结构与算法**。而有效地评估算法效率至关重要,因为只有了解评价标准,我们才能对比分析各种算法,从而指导算法设计与优化过程。
 | 
				
			||||||
 | 
					
 | 
				
			||||||
## 效率评估方法
 | 
					效率评估方法主要分为两种:实际测试和理论估算。
 | 
				
			||||||
 | 
					
 | 
				
			||||||
### 实际测试
 | 
					## 实际测试
 | 
				
			||||||
 | 
					
 | 
				
			||||||
假设我们现在有算法 `A` 和算法 `B` ,它们都能解决同一问题,现在需要对比这两个算法的效率。最直接的方法是找一台计算机,运行这两个算法,并监控记录它们的运行时间和内存占用情况。这种评估方式能够反映真实情况,但也存在较大局限性。
 | 
					假设我们现在有算法 `A` 和算法 `B` ,它们都能解决同一问题,现在需要对比这两个算法的效率。最直接的方法是找一台计算机,运行这两个算法,并监控记录它们的运行时间和内存占用情况。这种评估方式能够反映真实情况,但也存在较大局限性。
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -24,7 +22,7 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
**展开完整测试非常耗费资源**。随着输入数据量的变化,算法会表现出不同的效率。例如,在输入数据量较小时,算法 `A` 的运行时间比算法 `B` 更少;而输入数据量较大时,测试结果可能恰恰相反。因此,为了得到有说服力的结论,我们需要测试各种规模的输入数据,而这样需要耗费大量的计算资源。
 | 
					**展开完整测试非常耗费资源**。随着输入数据量的变化,算法会表现出不同的效率。例如,在输入数据量较小时,算法 `A` 的运行时间比算法 `B` 更少;而输入数据量较大时,测试结果可能恰恰相反。因此,为了得到有说服力的结论,我们需要测试各种规模的输入数据,而这样需要耗费大量的计算资源。
 | 
				
			||||||
 | 
					
 | 
				
			||||||
### 理论估算
 | 
					## 理论估算
 | 
				
			||||||
 | 
					
 | 
				
			||||||
由于实际测试具有较大的局限性,我们可以考虑仅通过一些计算来评估算法的效率。这种估算方法被称为「渐近复杂度分析 Asymptotic Complexity Analysis」,简称为「复杂度分析」。
 | 
					由于实际测试具有较大的局限性,我们可以考虑仅通过一些计算来评估算法的效率。这种估算方法被称为「渐近复杂度分析 Asymptotic Complexity Analysis」,简称为「复杂度分析」。
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -3,7 +3,7 @@
 | 
				
			|||||||
- 分治算法是一种常见的算法设计策略,包括分(划分)和治(合并)两个阶段,通常基于递归实现。
 | 
					- 分治算法是一种常见的算法设计策略,包括分(划分)和治(合并)两个阶段,通常基于递归实现。
 | 
				
			||||||
- 判断是否是分治算法问题的依据包括:问题能否被分解、子问题是否独立、子问题是否可以被合并。
 | 
					- 判断是否是分治算法问题的依据包括:问题能否被分解、子问题是否独立、子问题是否可以被合并。
 | 
				
			||||||
- 归并排序是分治策略的典型应用,其递归地将数组划分为等长的两个子数组,直到只剩一个元素时开始逐层合并,从而完成排序。
 | 
					- 归并排序是分治策略的典型应用,其递归地将数组划分为等长的两个子数组,直到只剩一个元素时开始逐层合并,从而完成排序。
 | 
				
			||||||
- 引入分治策略往往可以带来算法效率的提升。一方面,分治策略减少了计算吧操作数量;另一方面,分治后有利于系统的并行优化。
 | 
					- 引入分治策略往往可以带来算法效率的提升。一方面,分治策略减少了计算操作数量;另一方面,分治后有利于系统的并行优化。
 | 
				
			||||||
- 分治既可以解决许多算法问题,也广泛应用于数据结构与算法设计中,处处可见其身影。
 | 
					- 分治既可以解决许多算法问题,也广泛应用于数据结构与算法设计中,处处可见其身影。
 | 
				
			||||||
- 相较于暴力搜索,自适应搜索效率更高。时间复杂度为 $O(\log n)$ 的搜索算法通常都是基于分治策略实现的。
 | 
					- 相较于暴力搜索,自适应搜索效率更高。时间复杂度为 $O(\log n)$ 的搜索算法通常都是基于分治策略实现的。
 | 
				
			||||||
- 二分查找是分治思想的另一个典型应用,它不包含将子问题的解进行合并的步骤。我们可以通过递归分治实现二分查找。
 | 
					- 二分查找是分治思想的另一个典型应用,它不包含将子问题的解进行合并的步骤。我们可以通过递归分治实现二分查找。
 | 
				
			||||||
 | 
				
			|||||||
@ -9,6 +9,8 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
## 二叉搜索树的操作
 | 
					## 二叉搜索树的操作
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					我们将二叉搜索树封装为一个类 `ArrayBinaryTree` ,并声明一个成员变量 `root` ,指向树的根节点。
 | 
				
			||||||
 | 
					
 | 
				
			||||||
### 查找节点
 | 
					### 查找节点
 | 
				
			||||||
 | 
					
 | 
				
			||||||
给定目标节点值 `num` ,可以根据二叉搜索树的性质来查找。我们声明一个节点 `cur` ,从二叉树的根节点 `root` 出发,循环比较节点值 `cur.val` 和 `num` 之间的大小关系
 | 
					给定目标节点值 `num` ,可以根据二叉搜索树的性质来查找。我们声明一个节点 `cur` ,从二叉树的根节点 `root` 出发,循环比较节点值 `cur.val` 和 `num` 之间的大小关系
 | 
				
			||||||
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user