vault backup: 2026-06-10 11:19:43
This commit is contained in:
+69
-39
@@ -65,13 +65,21 @@ flowchart TD
|
||||
|
||||
归并排序是分治法最经典的应用之一,时间复杂度 **O(n logn)**。
|
||||
|
||||
```plaintext
|
||||
function mergeSort(A, left, right):
|
||||
if left < right:
|
||||
mid = (left + right) / 2
|
||||
mergeSort(A, left, mid) // 分解:排序左半部分
|
||||
mergeSort(A, mid+1, right) // 分解:排序右半部分
|
||||
merge(A, left, mid, right) // 合并:合并两个有序子数组
|
||||
```cpp
|
||||
#include <vector>
|
||||
using namespace std;
|
||||
|
||||
// merge函数省略,此处仅展示归并排序的分治骨架
|
||||
// void merge(vector<int>& A, int left, int mid, int right) { ... }
|
||||
|
||||
void mergeSort(vector<int>& A, int left, int right) {
|
||||
if (left < right) {
|
||||
int mid = (left + right) / 2;
|
||||
mergeSort(A, left, mid); // 分解:排序左半部分
|
||||
mergeSort(A, mid + 1, right); // 分解:排序右半部分
|
||||
// merge(A, left, mid, right); // 合并:合并两个有序子数组
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
- **分解**:将数组从中间分为两半
|
||||
@@ -95,28 +103,42 @@ function mergeSort(A, left, right):
|
||||
- 每组2个元素:组内比较1次,再与当前最大、最小各比较1次
|
||||
- 比较次数从 **2(n-1)** 降至约 **3n/2**
|
||||
|
||||
```plaintext
|
||||
function findMaxMin(A, n):
|
||||
// 初始化
|
||||
if n is odd:
|
||||
maxVal = minVal = A[1]
|
||||
start = 2
|
||||
else:
|
||||
if A[1] < A[2]:
|
||||
minVal = A[1], maxVal = A[2]
|
||||
else:
|
||||
minVal = A[2], maxVal = A[1]
|
||||
start = 3
|
||||
```cpp
|
||||
#include <vector>
|
||||
#include <utility>
|
||||
using namespace std;
|
||||
|
||||
// 两两比较
|
||||
for i = start to n step 2:
|
||||
if A[i] < A[i+1]:
|
||||
smaller, larger = A[i], A[i+1]
|
||||
else:
|
||||
smaller, larger = A[i+1], A[i]
|
||||
if smaller < minVal: minVal = smaller
|
||||
if larger > maxVal: maxVal = larger
|
||||
return (maxVal, minVal)
|
||||
// 同时求最大值和最小值,比较次数约 3n/2
|
||||
pair<int, int> findMaxMin(vector<int>& A, int n) {
|
||||
int maxVal, minVal;
|
||||
int start;
|
||||
|
||||
// 初始化:根据元素个数的奇偶性决定初始值
|
||||
if (n % 2 == 1) {
|
||||
maxVal = minVal = A[0];
|
||||
start = 1;
|
||||
} else {
|
||||
if (A[0] < A[1]) {
|
||||
minVal = A[0]; maxVal = A[1];
|
||||
} else {
|
||||
minVal = A[1]; maxVal = A[0];
|
||||
}
|
||||
start = 2;
|
||||
}
|
||||
|
||||
// 两两比较:每组内比较1次,再分别与全局最大最小比较
|
||||
for (int i = start; i < n; i += 2) {
|
||||
int smaller, larger;
|
||||
if (A[i] < A[i + 1]) {
|
||||
smaller = A[i]; larger = A[i + 1];
|
||||
} else {
|
||||
smaller = A[i + 1]; larger = A[i];
|
||||
}
|
||||
if (smaller < minVal) minVal = smaller;
|
||||
if (larger > maxVal) maxVal = larger;
|
||||
}
|
||||
return {maxVal, minVal};
|
||||
}
|
||||
```
|
||||
|
||||
**解释**:每次循环处理两个元素,组内比较1次确定大小,再分别与全局最大最小比较最多2次,所以每组最多3次比较。总比较次数约为 3(n-1)/2。
|
||||
@@ -129,17 +151,25 @@ function findMaxMin(A, n):
|
||||
2. 只有当某个元素**大于当前最大值**时,才更新第二大值
|
||||
3. 一次遍历即可完成
|
||||
|
||||
```plaintext
|
||||
function findSecondMax(A, n):
|
||||
maxVal = A[1]
|
||||
secondMax = -infinity
|
||||
for i = 2 to n:
|
||||
if A[i] > maxVal:
|
||||
secondMax = maxVal // 原来的最大变为第二
|
||||
maxVal = A[i] // 更新最大
|
||||
else if A[i] > secondMax:
|
||||
secondMax = A[i] // 更新第二
|
||||
return secondMax
|
||||
```cpp
|
||||
#include <vector>
|
||||
#include <climits>
|
||||
using namespace std;
|
||||
|
||||
// 一次遍历找第二大的数,时间O(n)
|
||||
int findSecondMax(vector<int>& A, int n) {
|
||||
int maxVal = A[0];
|
||||
int secondMax = INT_MIN;
|
||||
for (int i = 1; i < n; i++) {
|
||||
if (A[i] > maxVal) {
|
||||
secondMax = maxVal; // 原来的最大变为第二
|
||||
maxVal = A[i]; // 更新最大
|
||||
} else if (A[i] > secondMax) {
|
||||
secondMax = A[i]; // 更新第二
|
||||
}
|
||||
}
|
||||
return secondMax;
|
||||
}
|
||||
```
|
||||
|
||||
#### 4.5 伪币问题
|
||||
|
||||
Reference in New Issue
Block a user