Add cpp codes for the chapter
computational complexity, sorting, searching.
This commit is contained in:
parent
431a0f6caf
commit
19a4ccd86a
@ -10,6 +10,7 @@ class SolutionBruteForce {
|
|||||||
public:
|
public:
|
||||||
vector<int> twoSum(vector<int>& nums, int target) {
|
vector<int> twoSum(vector<int>& nums, int target) {
|
||||||
int size = nums.size();
|
int size = nums.size();
|
||||||
|
// 两层循环,时间复杂度 O(n^2)
|
||||||
for (int i = 0; i < size - 1; i++) {
|
for (int i = 0; i < size - 1; i++) {
|
||||||
for (int j = i + 1; j < size; j++) {
|
for (int j = i + 1; j < size; j++) {
|
||||||
if (nums[i] + nums[j] == target)
|
if (nums[i] + nums[j] == target)
|
||||||
@ -24,7 +25,9 @@ class SolutionHashMap {
|
|||||||
public:
|
public:
|
||||||
vector<int> twoSum(vector<int>& nums, int target) {
|
vector<int> twoSum(vector<int>& nums, int target) {
|
||||||
int size = nums.size();
|
int size = nums.size();
|
||||||
|
// 辅助哈希表,空间复杂度 O(n)
|
||||||
unordered_map<int, int> dic;
|
unordered_map<int, int> dic;
|
||||||
|
// 单层循环,时间复杂度 O(n)
|
||||||
for (int i = 0; i < size; i++) {
|
for (int i = 0; i < size; i++) {
|
||||||
if (dic.find(target - nums[i]) != dic.end()) {
|
if (dic.find(target - nums[i]) != dic.end()) {
|
||||||
return { dic[target - nums[i]], i };
|
return { dic[target - nums[i]], i };
|
||||||
@ -45,9 +48,13 @@ int main() {
|
|||||||
// 方法一
|
// 方法一
|
||||||
SolutionBruteForce* slt1 = new SolutionBruteForce();
|
SolutionBruteForce* slt1 = new SolutionBruteForce();
|
||||||
vector<int> res = slt1->twoSum(nums, target);
|
vector<int> res = slt1->twoSum(nums, target);
|
||||||
|
cout << "方法一 res = ";
|
||||||
PrintUtil::printVector(res);
|
PrintUtil::printVector(res);
|
||||||
// 方法二
|
// 方法二
|
||||||
SolutionHashMap* slt2 = new SolutionHashMap();
|
SolutionHashMap* slt2 = new SolutionHashMap();
|
||||||
res = slt2->twoSum(nums, target);
|
res = slt2->twoSum(nums, target);
|
||||||
|
cout << "方法二 res = ";
|
||||||
PrintUtil::printVector(res);
|
PrintUtil::printVector(res);
|
||||||
|
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -6,3 +6,97 @@
|
|||||||
|
|
||||||
#include "../include/include.hpp"
|
#include "../include/include.hpp"
|
||||||
|
|
||||||
|
/* 函数 */
|
||||||
|
int func() {
|
||||||
|
// do something
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 常数阶 */
|
||||||
|
void constant(int n) {
|
||||||
|
// 常量、变量、对象占用 O(1) 空间
|
||||||
|
const int a = 0;
|
||||||
|
int b = 0;
|
||||||
|
vector<int> nums(10000);
|
||||||
|
ListNode* node = new ListNode(0);
|
||||||
|
// 循环中的变量占用 O(1) 空间
|
||||||
|
for (int i = 0; i < n; i++) {
|
||||||
|
int c = 0;
|
||||||
|
}
|
||||||
|
// 循环中的函数占用 O(1) 空间
|
||||||
|
for (int i = 0; i < n; i++) {
|
||||||
|
func();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 线性阶 */
|
||||||
|
void linear(int n) {
|
||||||
|
// 长度为 n 的数组占用 O(n) 空间
|
||||||
|
vector<int> nums(n);
|
||||||
|
// 长度为 n 的列表占用 O(n) 空间
|
||||||
|
vector<ListNode*> nodes;
|
||||||
|
for (int i = 0; i < n; i++) {
|
||||||
|
nodes.push_back(new ListNode(i));
|
||||||
|
}
|
||||||
|
// 长度为 n 的哈希表占用 O(n) 空间
|
||||||
|
unordered_map<int, string> map;
|
||||||
|
for (int i = 0; i < n; i++) {
|
||||||
|
map[i] = to_string(i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 线性阶(递归实现) */
|
||||||
|
void linearRecur(int n) {
|
||||||
|
cout << "递归 n = " << n << endl;
|
||||||
|
if (n == 1) return;
|
||||||
|
linearRecur(n - 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 平方阶 */
|
||||||
|
void quadratic(int n) {
|
||||||
|
// 二维列表占用 O(n^2) 空间
|
||||||
|
vector<vector<int>> numMatrix;
|
||||||
|
for (int i = 0; i < n; i++) {
|
||||||
|
vector<int> tmp;
|
||||||
|
for (int j = 0; j < n; j++) {
|
||||||
|
tmp.push_back(0);
|
||||||
|
}
|
||||||
|
numMatrix.push_back(tmp);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 平方阶(递归实现) */
|
||||||
|
int quadraticRecur(int n) {
|
||||||
|
if (n <= 0) return 0;
|
||||||
|
vector<int> nums(n);
|
||||||
|
cout << "递归 n = " << n << " 中的 nums 长度 = " << nums.size() << endl;
|
||||||
|
return quadraticRecur(n - 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 指数阶(建立满二叉树) */
|
||||||
|
TreeNode* buildTree(int n) {
|
||||||
|
if (n == 0) return nullptr;
|
||||||
|
TreeNode* root = new TreeNode(0);
|
||||||
|
root->left = buildTree(n - 1);
|
||||||
|
root->right = buildTree(n - 1);
|
||||||
|
return root;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* Driver Code */
|
||||||
|
int main() {
|
||||||
|
int n = 5;
|
||||||
|
// 常数阶
|
||||||
|
constant(n);
|
||||||
|
// 线性阶
|
||||||
|
linear(n);
|
||||||
|
linearRecur(n);
|
||||||
|
// 平方阶
|
||||||
|
quadratic(n);
|
||||||
|
quadraticRecur(n);
|
||||||
|
// 指数阶
|
||||||
|
TreeNode* root = buildTree(n);
|
||||||
|
PrintUtil::printTree(root);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
@ -6,3 +6,161 @@
|
|||||||
|
|
||||||
#include "../include/include.hpp"
|
#include "../include/include.hpp"
|
||||||
|
|
||||||
|
/* 常数阶 */
|
||||||
|
int constant(int n) {
|
||||||
|
int count = 0;
|
||||||
|
int size = 100000;
|
||||||
|
for (int i = 0; i < size; i++)
|
||||||
|
count++;
|
||||||
|
return count;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 线性阶 */
|
||||||
|
int linear(int n) {
|
||||||
|
int count = 0;
|
||||||
|
for (int i = 0; i < n; i++)
|
||||||
|
count++;
|
||||||
|
return count;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 线性阶(遍历数组) */
|
||||||
|
int arrayTraversal(vector<int>& nums) {
|
||||||
|
int count = 0;
|
||||||
|
// 循环次数与数组长度成正比
|
||||||
|
for (int num : nums) {
|
||||||
|
count++;
|
||||||
|
}
|
||||||
|
return count;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 平方阶 */
|
||||||
|
int quadratic(int n) {
|
||||||
|
int count = 0;
|
||||||
|
// 循环次数与数组长度成平方关系
|
||||||
|
for (int i = 0; i < n; i++) {
|
||||||
|
for (int j = 0; j < n; j++) {
|
||||||
|
count++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return count;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 平方阶(冒泡排序) */
|
||||||
|
int bubbleSort(vector<int>& nums) {
|
||||||
|
int count = 0; // 计数器
|
||||||
|
// 外循环:待排序元素数量为 n-1, n-2, ..., 1
|
||||||
|
for (int i = nums.size() - 1; i > 0; i--) {
|
||||||
|
// 内循环:冒泡操作
|
||||||
|
for (int j = 0; j < i; j++) {
|
||||||
|
if (nums[j] > nums[j + 1]) {
|
||||||
|
// 交换 nums[j] 与 nums[j + 1]
|
||||||
|
int tmp = nums[j];
|
||||||
|
nums[j] = nums[j + 1];
|
||||||
|
nums[j + 1] = tmp;
|
||||||
|
count += 3; // 元素交换包含 3 个单元操作
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return count;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 指数阶(循环实现) */
|
||||||
|
int exponential(int n) {
|
||||||
|
int count = 0, base = 1;
|
||||||
|
// cell 每轮一分为二,形成数列 1, 2, 4, 8, ..., 2^(n-1)
|
||||||
|
for (int i = 0; i < n; i++) {
|
||||||
|
for (int j = 0; j < base; j++) {
|
||||||
|
count++;
|
||||||
|
}
|
||||||
|
base *= 2;
|
||||||
|
}
|
||||||
|
// count = 1 + 2 + 4 + 8 + .. + 2^(n-1) = 2^n - 1
|
||||||
|
return count;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 指数阶(递归实现) */
|
||||||
|
int expRecur(int n) {
|
||||||
|
if (n == 1) return 1;
|
||||||
|
return expRecur(n - 1) + expRecur(n - 1) + 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 对数阶(循环实现) */
|
||||||
|
int logarithmic(float n) {
|
||||||
|
int count = 0;
|
||||||
|
while (n > 1) {
|
||||||
|
n = n / 2;
|
||||||
|
count++;
|
||||||
|
}
|
||||||
|
return count;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 对数阶(递归实现) */
|
||||||
|
int logRecur(float n) {
|
||||||
|
if (n <= 1) return 0;
|
||||||
|
return logRecur(n / 2) + 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 线性对数阶 */
|
||||||
|
int linearLogRecur(float n) {
|
||||||
|
if (n <= 1) return 1;
|
||||||
|
int count = linearLogRecur(n / 2) +
|
||||||
|
linearLogRecur(n / 2);
|
||||||
|
for (int i = 0; i < n; i++) {
|
||||||
|
count++;
|
||||||
|
}
|
||||||
|
return count;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 阶乘阶(递归实现) */
|
||||||
|
int factorialRecur(int n) {
|
||||||
|
if (n == 0) return 1;
|
||||||
|
int count = 0;
|
||||||
|
// 从 1 个分裂出 n 个
|
||||||
|
for (int i = 0; i < n; i++) {
|
||||||
|
count += factorialRecur(n - 1);
|
||||||
|
}
|
||||||
|
return count;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* Driver Code */
|
||||||
|
int main() {
|
||||||
|
// 可以修改 n 运行,体会一下各种复杂度的操作数量变化趋势
|
||||||
|
int n = 8;
|
||||||
|
cout << "输入数据大小 n = " << n << endl;
|
||||||
|
|
||||||
|
int count = constant(n);
|
||||||
|
cout << "常数阶的计算操作数量 = " << count << endl;
|
||||||
|
|
||||||
|
count = linear(n);
|
||||||
|
cout << "线性阶的计算操作数量 = " << count << endl;
|
||||||
|
vector<int> arr(n);
|
||||||
|
count = arrayTraversal(arr);
|
||||||
|
cout << "线性阶(遍历数组)的计算操作数量 = " << count << endl;
|
||||||
|
|
||||||
|
count = quadratic(n);
|
||||||
|
cout << "平方阶的计算操作数量 = " << count << endl;
|
||||||
|
vector<int> nums(n);
|
||||||
|
for (int i = 0; i < n; i++)
|
||||||
|
nums[i] = n - i; // [n,n-1,...,2,1]
|
||||||
|
count = bubbleSort(nums);
|
||||||
|
cout << "平方阶(冒泡排序)的计算操作数量 = " << count << endl;
|
||||||
|
|
||||||
|
count = exponential(n);
|
||||||
|
cout << "指数阶(循环实现)的计算操作数量 = " << count << endl;
|
||||||
|
count = expRecur(n);
|
||||||
|
cout << "指数阶(递归实现)的计算操作数量 = " << count << endl;
|
||||||
|
|
||||||
|
count = logarithmic((float) n);
|
||||||
|
cout << "对数阶(循环实现)的计算操作数量 = " << count << endl;
|
||||||
|
count = logRecur((float) n);
|
||||||
|
cout << "对数阶(递归实现)的计算操作数量 = " << count << endl;
|
||||||
|
|
||||||
|
count = linearLogRecur((float) n);
|
||||||
|
cout << "线性对数阶(递归实现)的计算操作数量 = " << count << endl;
|
||||||
|
|
||||||
|
count = factorialRecur(n);
|
||||||
|
cout << "阶乘阶(递归实现)的计算操作数量 = " << count << endl;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
@ -6,3 +6,39 @@
|
|||||||
|
|
||||||
#include "../include/include.hpp"
|
#include "../include/include.hpp"
|
||||||
|
|
||||||
|
/* 生成一个数组,元素为 { 1, 2, ..., n },顺序被打乱 */
|
||||||
|
vector<int> randomNumbers(int n) {
|
||||||
|
vector<int> nums(n);
|
||||||
|
// 生成数组 nums = { 1, 2, 3, ..., n }
|
||||||
|
for (int i = 0; i < n; i++) {
|
||||||
|
nums[i] = i + 1;
|
||||||
|
}
|
||||||
|
// 使用系统时间生成随机种子
|
||||||
|
unsigned seed = chrono::system_clock::now().time_since_epoch().count();
|
||||||
|
// 随机打乱数组元素
|
||||||
|
shuffle(nums.begin(), nums.end(), default_random_engine(seed));
|
||||||
|
return nums;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 查找数组 nums 中数字 1 所在索引 */
|
||||||
|
int findOne(vector<int>& nums) {
|
||||||
|
for (int i = 0; i < nums.size(); i++) {
|
||||||
|
if (nums[i] == 1)
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* Driver Code */
|
||||||
|
int main() {
|
||||||
|
for (int i = 0; i < 1000; i++) {
|
||||||
|
int n = 100;
|
||||||
|
vector<int> nums = randomNumbers(n);
|
||||||
|
int index = findOne(nums);
|
||||||
|
cout << "\n数组 [ 1, 2, ..., n ] 被打乱后 = ";
|
||||||
|
PrintUtil::printVector(nums);
|
||||||
|
cout << "数字 1 的索引为 " << index << endl;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
@ -6,3 +6,55 @@
|
|||||||
|
|
||||||
#include "../include/include.hpp"
|
#include "../include/include.hpp"
|
||||||
|
|
||||||
|
/* 二分查找(双闭区间) */
|
||||||
|
int binarySearch(vector<int>& nums, int target) {
|
||||||
|
// 初始化双闭区间 [0, n-1] ,即 i, j 分别指向数组首元素、尾元素
|
||||||
|
int i = 0, j = nums.size() - 1;
|
||||||
|
// 循环,当搜索区间为空时跳出(当 i > j 时为空)
|
||||||
|
while (i <= j) {
|
||||||
|
int m = (i + j) / 2; // 计算中点索引 m
|
||||||
|
if (nums[m] < target) // 此情况说明 target 在区间 [m+1, j] 中
|
||||||
|
i = m + 1;
|
||||||
|
else if (nums[m] > target) // 此情况说明 target 在区间 [i, m-1] 中
|
||||||
|
j = m - 1;
|
||||||
|
else // 找到目标元素,返回其索引
|
||||||
|
return m;
|
||||||
|
}
|
||||||
|
// 未找到目标元素,返回 -1
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 二分查找(左闭右开) */
|
||||||
|
int binarySearch1(vector<int>& nums, int target) {
|
||||||
|
// 初始化左闭右开 [0, n) ,即 i, j 分别指向数组首元素、尾元素+1
|
||||||
|
int i = 0, j = nums.size();
|
||||||
|
// 循环,当搜索区间为空时跳出(当 i = j 时为空)
|
||||||
|
while (i < j) {
|
||||||
|
int m = (i + j) / 2; // 计算中点索引 m
|
||||||
|
if (nums[m] < target) // 此情况说明 target 在区间 [m+1, j) 中
|
||||||
|
i = m + 1;
|
||||||
|
else if (nums[m] > target) // 此情况说明 target 在区间 [i, m) 中
|
||||||
|
j = m;
|
||||||
|
else // 找到目标元素,返回其索引
|
||||||
|
return m;
|
||||||
|
}
|
||||||
|
// 未找到目标元素,返回 -1
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* Driver Code */
|
||||||
|
int main() {
|
||||||
|
int target = 6;
|
||||||
|
vector<int> nums = { 1, 3, 6, 8, 12, 15, 23, 67, 70, 92 };
|
||||||
|
|
||||||
|
/* 二分查找(双闭区间) */
|
||||||
|
int index = binarySearch(nums, target);
|
||||||
|
cout << "目标元素 6 的索引 = " << index << endl;
|
||||||
|
|
||||||
|
/* 二分查找(左闭右开) */
|
||||||
|
index = binarySearch1(nums, target);
|
||||||
|
cout << "目标元素 6 的索引 = " << index << endl;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
@ -6,3 +6,49 @@
|
|||||||
|
|
||||||
#include "../include/include.hpp"
|
#include "../include/include.hpp"
|
||||||
|
|
||||||
|
/* 哈希查找(数组) */
|
||||||
|
int hashingSearch(unordered_map<int, int> map, int target) {
|
||||||
|
// 哈希表的 key: 目标元素,value: 索引
|
||||||
|
// 若哈希表中无此 key ,返回 -1
|
||||||
|
if (map.find(target) == map.end())
|
||||||
|
return -1;
|
||||||
|
return map[target];
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 哈希查找(链表) */
|
||||||
|
ListNode* hashingSearch1(unordered_map<int, ListNode*> map, int target) {
|
||||||
|
// 哈希表的 key: 目标结点值,value: 结点对象
|
||||||
|
// 若哈希表中无此 key ,返回 nullptr
|
||||||
|
if (map.find(target) == map.end())
|
||||||
|
return nullptr;
|
||||||
|
return map[target];
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* Driver Code */
|
||||||
|
int main() {
|
||||||
|
int target = 3;
|
||||||
|
|
||||||
|
/* 哈希查找(数组) */
|
||||||
|
vector<int> nums = { 1, 5, 3, 2, 4, 7, 5, 9, 10, 8 };
|
||||||
|
// 初始化哈希表
|
||||||
|
unordered_map<int, int> map;
|
||||||
|
for (int i = 0; i < nums.size(); i++) {
|
||||||
|
map[nums[i]] = i; // key: 元素,value: 索引
|
||||||
|
}
|
||||||
|
int index = hashingSearch(map, target);
|
||||||
|
cout << "目标元素 3 的索引 = " << index << endl;
|
||||||
|
|
||||||
|
/* 哈希查找(链表) */
|
||||||
|
ListNode* head = vectorToLinkedList(nums);
|
||||||
|
// 初始化哈希表
|
||||||
|
unordered_map<int, ListNode*> map1;
|
||||||
|
while (head != nullptr) {
|
||||||
|
map1[head->val] = head; // key: 结点值,value: 结点
|
||||||
|
head = head->next;
|
||||||
|
}
|
||||||
|
ListNode* node = hashingSearch1(map1, target);
|
||||||
|
cout << "目标结点值 3 的对应结点对象为 " << node << endl;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
@ -6,3 +6,45 @@
|
|||||||
|
|
||||||
#include "../include/include.hpp"
|
#include "../include/include.hpp"
|
||||||
|
|
||||||
|
/* 线性查找(数组) */
|
||||||
|
int linearSearch(vector<int>& nums, int target) {
|
||||||
|
// 遍历数组
|
||||||
|
for (int i = 0; i < nums.size(); i++) {
|
||||||
|
// 找到目标元素,返回其索引
|
||||||
|
if (nums[i] == target)
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
// 未找到目标元素,返回 -1
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 线性查找(链表) */
|
||||||
|
ListNode* linearSearch(ListNode* head, int target) {
|
||||||
|
// 遍历链表
|
||||||
|
while (head != nullptr) {
|
||||||
|
// 找到目标结点,返回之
|
||||||
|
if (head->val == target)
|
||||||
|
return head;
|
||||||
|
head = head->next;
|
||||||
|
}
|
||||||
|
// 未找到目标结点,返回 nullptr
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* Driver Code */
|
||||||
|
int main() {
|
||||||
|
int target = 3;
|
||||||
|
|
||||||
|
/* 在数组中执行线性查找 */
|
||||||
|
vector<int> nums = { 1, 5, 3, 2, 4, 7, 5, 9, 10, 8 };
|
||||||
|
int index = linearSearch(nums, target);
|
||||||
|
cout << "目标元素 3 的索引 = " << index << endl;
|
||||||
|
|
||||||
|
/* 在链表中执行线性查找 */
|
||||||
|
ListNode* head = vectorToLinkedList(nums);
|
||||||
|
ListNode* node = linearSearch(head, target);
|
||||||
|
cout << "目标结点值 3 的对应结点对象为 " << node << endl;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
@ -6,3 +6,53 @@
|
|||||||
|
|
||||||
#include "../include/include.hpp"
|
#include "../include/include.hpp"
|
||||||
|
|
||||||
|
/* 冒泡排序 */
|
||||||
|
void bubbleSort(vector<int>& nums) {
|
||||||
|
// 外循环:待排序元素数量为 n-1, n-2, ..., 1
|
||||||
|
for (int i = nums.size() - 1; i > 0; i--) {
|
||||||
|
// 内循环:冒泡操作
|
||||||
|
for (int j = 0; j < i; j++) {
|
||||||
|
if (nums[j] > nums[j + 1]) {
|
||||||
|
// 交换 nums[j] 与 nums[j + 1]
|
||||||
|
int tmp = nums[j];
|
||||||
|
nums[j] = nums[j + 1];
|
||||||
|
nums[j + 1] = tmp;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 冒泡排序(标志优化)*/
|
||||||
|
void bubbleSortWithFlag(vector<int>& nums) {
|
||||||
|
// 外循环:待排序元素数量为 n-1, n-2, ..., 1
|
||||||
|
for (int i = nums.size() - 1; i > 0; i--) {
|
||||||
|
bool flag = false; // 初始化标志位
|
||||||
|
// 内循环:冒泡操作
|
||||||
|
for (int j = 0; j < i; j++) {
|
||||||
|
if (nums[j] > nums[j + 1]) {
|
||||||
|
// 交换 nums[j] 与 nums[j + 1]
|
||||||
|
int tmp = nums[j];
|
||||||
|
nums[j] = nums[j + 1];
|
||||||
|
nums[j + 1] = tmp;
|
||||||
|
flag = true; // 记录交换元素
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!flag) break; // 此轮冒泡未交换任何元素,直接跳出
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* Driver Code */
|
||||||
|
int main() {
|
||||||
|
vector<int> nums = { 4, 1, 3, 1, 5, 2 };
|
||||||
|
bubbleSort(nums);
|
||||||
|
cout << "冒泡排序完成后 nums = ";
|
||||||
|
PrintUtil::printVector(nums);
|
||||||
|
|
||||||
|
vector<int> nums1 = { 4, 1, 3, 1, 5, 2 };
|
||||||
|
bubbleSortWithFlag(nums1);
|
||||||
|
cout << "冒泡排序完成后 nums1 = ";
|
||||||
|
PrintUtil::printVector(nums1);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
@ -6,3 +6,27 @@
|
|||||||
|
|
||||||
#include "../include/include.hpp"
|
#include "../include/include.hpp"
|
||||||
|
|
||||||
|
/* 插入排序 */
|
||||||
|
void insertionSort(vector<int>& nums) {
|
||||||
|
// 外循环:base = nums[1], nums[2], ..., nums[n-1]
|
||||||
|
for (int i = 1; i < nums.size(); i++) {
|
||||||
|
int base = nums[i], j = i - 1;
|
||||||
|
// 内循环:将 base 插入到左边的正确位置
|
||||||
|
while (j >= 0 && nums[j] > base) {
|
||||||
|
nums[j + 1] = nums[j]; // 1. 将 nums[j] 向右移动一位
|
||||||
|
j--;
|
||||||
|
}
|
||||||
|
nums[j + 1] = base; // 2. 将 base 赋值到正确位置
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* Driver Code */
|
||||||
|
int main() {
|
||||||
|
vector<int> nums = { 4, 1, 3, 1, 5, 2 };
|
||||||
|
insertionSort(nums);
|
||||||
|
cout << "插入排序完成后 nums = ";
|
||||||
|
PrintUtil::printVector(nums);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
@ -6,3 +6,54 @@
|
|||||||
|
|
||||||
#include "../include/include.hpp"
|
#include "../include/include.hpp"
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 合并左子数组和右子数组
|
||||||
|
* 左子数组区间 [left, mid]
|
||||||
|
* 右子数组区间 [mid + 1, right]
|
||||||
|
*/
|
||||||
|
void merge(vector<int>& nums, int left, int mid, int right) {
|
||||||
|
// 初始化辅助数组
|
||||||
|
vector<int> tmp(nums.begin() + left, nums.begin() + right + 1);
|
||||||
|
// 左子数组的起始索引和结束索引
|
||||||
|
int leftStart = left - left, leftEnd = mid - left;
|
||||||
|
// 右子数组的起始索引和结束索引
|
||||||
|
int rightStart = mid + 1 - left, rightEnd = right - left;
|
||||||
|
// i, j 分别指向左子数组、右子数组的首元素
|
||||||
|
int i = leftStart, j = rightStart;
|
||||||
|
// 通过覆盖原数组 nums 来合并左子数组和右子数组
|
||||||
|
for (int k = left; k <= right; k++) {
|
||||||
|
// 若 “左子数组已全部合并完”,则选取右子数组元素,并且 j++
|
||||||
|
if (i > leftEnd)
|
||||||
|
nums[k] = tmp[j++];
|
||||||
|
// 否则,若 “右子数组已全部合并完” 或 “左子数组元素 < 右子数组元素”,则选取左子数组元素,并且 i++
|
||||||
|
else if (j > rightEnd || tmp[i] <= tmp[j])
|
||||||
|
nums[k] = tmp[i++];
|
||||||
|
// 否则,若 “左子数组元素 > 右子数组元素”,则选取右子数组元素,并且 j++
|
||||||
|
else
|
||||||
|
nums[k] = tmp[j++];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 归并排序 */
|
||||||
|
void mergeSort(vector<int>& nums, int left, int right) {
|
||||||
|
// 终止条件
|
||||||
|
if (left >= right) return; // 当子数组长度为 1 时终止递归
|
||||||
|
// 划分阶段
|
||||||
|
int mid = (left + right) / 2; // 计算中点
|
||||||
|
mergeSort(nums, left, mid); // 递归左子数组
|
||||||
|
mergeSort(nums, mid + 1, right); // 递归右子数组
|
||||||
|
// 合并阶段
|
||||||
|
merge(nums, left, mid, right);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* Driver Code */
|
||||||
|
int main() {
|
||||||
|
/* 归并排序 */
|
||||||
|
vector<int> nums = { 7, 3, 2, 6, 0, 1, 5, 4 };
|
||||||
|
mergeSort(nums, 0, nums.size() - 1);
|
||||||
|
cout << "归并排序完成后 nums = ";
|
||||||
|
PrintUtil::printVector(nums);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
@ -6,3 +6,164 @@
|
|||||||
|
|
||||||
#include "../include/include.hpp"
|
#include "../include/include.hpp"
|
||||||
|
|
||||||
|
/* 快速排序类 */
|
||||||
|
class QuickSort {
|
||||||
|
private:
|
||||||
|
/* 元素交换 */
|
||||||
|
static void swap(vector<int>& nums, int i, int j) {
|
||||||
|
int tmp = nums[i];
|
||||||
|
nums[i] = nums[j];
|
||||||
|
nums[j] = tmp;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 哨兵划分 */
|
||||||
|
static int partition(vector<int>& nums, int left, int right) {
|
||||||
|
// 以 nums[left] 作为基准数
|
||||||
|
int i = left, j = right;
|
||||||
|
while (i < j) {
|
||||||
|
while (i < j && nums[j] >= nums[left])
|
||||||
|
j--; // 从右向左找首个小于基准数的元素
|
||||||
|
while (i < j && nums[i] <= nums[left])
|
||||||
|
i++; // 从左向右找首个大于基准数的元素
|
||||||
|
swap(nums, i, j); // 交换这两个元素
|
||||||
|
}
|
||||||
|
swap(nums, i, left); // 将基准数交换至两子数组的分界线
|
||||||
|
return i; // 返回基准数的索引
|
||||||
|
}
|
||||||
|
|
||||||
|
public:
|
||||||
|
/* 快速排序 */
|
||||||
|
static void quickSort(vector<int>& nums, int left, int right) {
|
||||||
|
// 子数组长度为 1 时终止递归
|
||||||
|
if (left >= right)
|
||||||
|
return;
|
||||||
|
// 哨兵划分
|
||||||
|
int pivot = partition(nums, left, right);
|
||||||
|
// 递归左子数组、右子数组
|
||||||
|
quickSort(nums, left, pivot - 1);
|
||||||
|
quickSort(nums, pivot + 1, right);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
/* 快速排序类(中位基准数优化) */
|
||||||
|
class QuickSortMedian {
|
||||||
|
private:
|
||||||
|
/* 元素交换 */
|
||||||
|
static void swap(vector<int>& nums, int i, int j) {
|
||||||
|
int tmp = nums[i];
|
||||||
|
nums[i] = nums[j];
|
||||||
|
nums[j] = tmp;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 选取三个元素的中位数 */
|
||||||
|
static int medianThree(vector<int>& nums, int left, int mid, int right) {
|
||||||
|
// 使用了异或操作来简化代码
|
||||||
|
// 异或规则为 0 ^ 0 = 1 ^ 1 = 0, 0 ^ 1 = 1 ^ 0 = 1
|
||||||
|
if ((nums[left] > nums[mid]) ^ (nums[left] > nums[right]))
|
||||||
|
return left;
|
||||||
|
else if ((nums[mid] < nums[left]) ^ (nums[mid] < nums[right]))
|
||||||
|
return mid;
|
||||||
|
else
|
||||||
|
return right;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 哨兵划分(三数取中值) */
|
||||||
|
static int partition(vector<int>& nums, int left, int right) {
|
||||||
|
// 选取三个候选元素的中位数
|
||||||
|
int med = medianThree(nums, left, (left + right) / 2, right);
|
||||||
|
// 将中位数交换至数组最左端
|
||||||
|
swap(nums, left, med);
|
||||||
|
// 以 nums[left] 作为基准数
|
||||||
|
int i = left, j = right;
|
||||||
|
while (i < j) {
|
||||||
|
while (i < j && nums[j] >= nums[left])
|
||||||
|
j--; // 从右向左找首个小于基准数的元素
|
||||||
|
while (i < j && nums[i] <= nums[left])
|
||||||
|
i++; // 从左向右找首个大于基准数的元素
|
||||||
|
swap(nums, i, j); // 交换这两个元素
|
||||||
|
}
|
||||||
|
swap(nums, i, left); // 将基准数交换至两子数组的分界线
|
||||||
|
return i; // 返回基准数的索引
|
||||||
|
}
|
||||||
|
|
||||||
|
public:
|
||||||
|
/* 快速排序 */
|
||||||
|
static void quickSort(vector<int>& nums, int left, int right) {
|
||||||
|
// 子数组长度为 1 时终止递归
|
||||||
|
if (left >= right)
|
||||||
|
return;
|
||||||
|
// 哨兵划分
|
||||||
|
int pivot = partition(nums, left, right);
|
||||||
|
// 递归左子数组、右子数组
|
||||||
|
quickSort(nums, left, pivot - 1);
|
||||||
|
quickSort(nums, pivot + 1, right);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
/* 快速排序类(尾递归优化) */
|
||||||
|
class QuickSortTailCall {
|
||||||
|
private:
|
||||||
|
/* 元素交换 */
|
||||||
|
static void swap(vector<int>& nums, int i, int j) {
|
||||||
|
int tmp = nums[i];
|
||||||
|
nums[i] = nums[j];
|
||||||
|
nums[j] = tmp;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 哨兵划分 */
|
||||||
|
static int partition(vector<int>& nums, int left, int right) {
|
||||||
|
// 以 nums[left] 作为基准数
|
||||||
|
int i = left, j = right;
|
||||||
|
while (i < j) {
|
||||||
|
while (i < j && nums[j] >= nums[left])
|
||||||
|
j--; // 从右向左找首个小于基准数的元素
|
||||||
|
while (i < j && nums[i] <= nums[left])
|
||||||
|
i++; // 从左向右找首个大于基准数的元素
|
||||||
|
swap(nums, i, j); // 交换这两个元素
|
||||||
|
}
|
||||||
|
swap(nums, i, left); // 将基准数交换至两子数组的分界线
|
||||||
|
return i; // 返回基准数的索引
|
||||||
|
}
|
||||||
|
|
||||||
|
public:
|
||||||
|
/* 快速排序(尾递归优化) */
|
||||||
|
static void quickSort(vector<int>& nums, int left, int right) {
|
||||||
|
// 子数组长度为 1 时终止
|
||||||
|
while (left < right) {
|
||||||
|
// 哨兵划分操作
|
||||||
|
int pivot = partition(nums, left, right);
|
||||||
|
// 对两个子数组中较短的那个执行快排
|
||||||
|
if (pivot - left < right - pivot) {
|
||||||
|
quickSort(nums, left, pivot - 1); // 递归排序左子数组
|
||||||
|
left = pivot + 1; // 剩余待排序区间为 [pivot + 1, right]
|
||||||
|
} else {
|
||||||
|
quickSort(nums, pivot + 1, right); // 递归排序右子数组
|
||||||
|
right = pivot - 1; // 剩余待排序区间为 [left, pivot - 1]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/* Driver Code */
|
||||||
|
int main() {
|
||||||
|
/* 快速排序 */
|
||||||
|
vector<int> nums { 2, 4, 1, 0, 3, 5 };
|
||||||
|
QuickSort::quickSort(nums, 0, nums.size() - 1);
|
||||||
|
cout << "快速排序完成后 nums = ";
|
||||||
|
PrintUtil::printVector(nums);
|
||||||
|
|
||||||
|
/* 快速排序(中位基准数优化) */
|
||||||
|
vector<int> nums1 = { 2, 4, 1, 0, 3, 5 };
|
||||||
|
QuickSortMedian::quickSort(nums1, 0, nums1.size() - 1);
|
||||||
|
cout << "快速排序(中位基准数优化)完成后 nums = ";
|
||||||
|
PrintUtil::printVector(nums);
|
||||||
|
|
||||||
|
/* 快速排序(尾递归优化) */
|
||||||
|
vector<int> nums2 = { 2, 4, 1, 0, 3, 5 };
|
||||||
|
QuickSortTailCall::quickSort(nums2, 0, nums2.size() - 1);
|
||||||
|
cout << "快速排序(尾递归优化)完成后 nums = ";
|
||||||
|
PrintUtil::printVector(nums);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
@ -25,7 +25,7 @@ struct ListNode {
|
|||||||
* @param list
|
* @param list
|
||||||
* @return ListNode*
|
* @return ListNode*
|
||||||
*/
|
*/
|
||||||
ListNode* vectorToLinkedList(vector<int> list) {
|
ListNode* vectorToLinkedList(vector<int>& list) {
|
||||||
ListNode *dum = new ListNode(0);
|
ListNode *dum = new ListNode(0);
|
||||||
ListNode *head = dum;
|
ListNode *head = dum;
|
||||||
for (int val : list) {
|
for (int val : list) {
|
||||||
|
@ -23,7 +23,7 @@ struct TreeNode {
|
|||||||
* @param list
|
* @param list
|
||||||
* @return TreeNode*
|
* @return TreeNode*
|
||||||
*/
|
*/
|
||||||
TreeNode* vectorToTree(vector<int> list) {
|
TreeNode* vectorToTree(vector<int>& list) {
|
||||||
TreeNode *root = new TreeNode(list[0]);
|
TreeNode *root = new TreeNode(list[0]);
|
||||||
queue<TreeNode*> que;
|
queue<TreeNode*> que;
|
||||||
que.emplace(root);
|
que.emplace(root);
|
||||||
|
@ -15,6 +15,7 @@
|
|||||||
#include <unordered_map>
|
#include <unordered_map>
|
||||||
#include <unordered_set>
|
#include <unordered_set>
|
||||||
#include <set>
|
#include <set>
|
||||||
|
#include <random>
|
||||||
|
|
||||||
#include "ListNode.hpp"
|
#include "ListNode.hpp"
|
||||||
#include "TreeNode.hpp"
|
#include "TreeNode.hpp"
|
||||||
|
@ -59,7 +59,7 @@ public class space_complexity_types {
|
|||||||
/* 平方阶 */
|
/* 平方阶 */
|
||||||
static void quadratic(int n) {
|
static void quadratic(int n) {
|
||||||
// 矩阵占用 O(n^2) 空间
|
// 矩阵占用 O(n^2) 空间
|
||||||
int numMatrix[][] = new int[n][n];
|
int[][] numMatrix = new int[n][n];
|
||||||
// 二维列表占用 O(n^2) 空间
|
// 二维列表占用 O(n^2) 空间
|
||||||
List<List<Integer>> numList = new ArrayList<>();
|
List<List<Integer>> numList = new ArrayList<>();
|
||||||
for (int i = 0; i < n; i++) {
|
for (int i = 0; i < n; i++) {
|
||||||
|
@ -20,7 +20,7 @@ public class hashing_search {
|
|||||||
/* 哈希查找(链表) */
|
/* 哈希查找(链表) */
|
||||||
static ListNode hashingSearch1(Map<Integer, ListNode> map, int target) {
|
static ListNode hashingSearch1(Map<Integer, ListNode> map, int target) {
|
||||||
// 哈希表的 key: 目标结点值,value: 结点对象
|
// 哈希表的 key: 目标结点值,value: 结点对象
|
||||||
// 若哈希表中无此 key ,返回 -1
|
// 若哈希表中无此 key ,返回 null
|
||||||
return map.getOrDefault(target, null);
|
return map.getOrDefault(target, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -9,7 +9,6 @@ package chapter_searching;
|
|||||||
import include.*;
|
import include.*;
|
||||||
|
|
||||||
public class linear_search {
|
public class linear_search {
|
||||||
|
|
||||||
/* 线性查找(数组) */
|
/* 线性查找(数组) */
|
||||||
static int linearSearch(int[] nums, int target) {
|
static int linearSearch(int[] nums, int target) {
|
||||||
// 遍历数组
|
// 遍历数组
|
||||||
|
@ -47,10 +47,10 @@ public class bubble_sort {
|
|||||||
public static void main(String[] args) {
|
public static void main(String[] args) {
|
||||||
int[] nums = { 4, 1, 3, 1, 5, 2 };
|
int[] nums = { 4, 1, 3, 1, 5, 2 };
|
||||||
bubbleSort(nums);
|
bubbleSort(nums);
|
||||||
System.out.println("排序后数组 nums = " + Arrays.toString(nums));
|
System.out.println("冒泡排序完成后 nums = " + Arrays.toString(nums));
|
||||||
|
|
||||||
int[] nums1 = { 4, 1, 3, 1, 5, 2 };
|
int[] nums1 = { 4, 1, 3, 1, 5, 2 };
|
||||||
bubbleSortWithFlag(nums1);
|
bubbleSortWithFlag(nums1);
|
||||||
System.out.println("排序后数组 nums1 = " + Arrays.toString(nums));
|
System.out.println("冒泡排序完成后 nums1 = " + Arrays.toString(nums));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -26,6 +26,6 @@ public class insertion_sort {
|
|||||||
public static void main(String[] args) {
|
public static void main(String[] args) {
|
||||||
int[] nums = { 4, 1, 3, 1, 5, 2 };
|
int[] nums = { 4, 1, 3, 1, 5, 2 };
|
||||||
insertionSort(nums);
|
insertionSort(nums);
|
||||||
System.out.println("排序后数组 nums = " + Arrays.toString(nums));
|
System.out.println("插入排序完成后 nums = " + Arrays.toString(nums));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -51,7 +51,7 @@ public class merge_sort {
|
|||||||
|
|
||||||
public static void main(String[] args) {
|
public static void main(String[] args) {
|
||||||
/* 归并排序 */
|
/* 归并排序 */
|
||||||
int[] nums = { 2, 4, 1, 0, 3, 5 };
|
int[] nums = { 7, 3, 2, 6, 0, 1, 5, 4 };
|
||||||
mergeSort(nums, 0, nums.length - 1);
|
mergeSort(nums, 0, nums.length - 1);
|
||||||
System.out.println("归并排序完成后 nums = " + Arrays.toString(nums));
|
System.out.println("归并排序完成后 nums = " + Arrays.toString(nums));
|
||||||
}
|
}
|
||||||
|
@ -37,7 +37,7 @@ def linear(n):
|
|||||||
|
|
||||||
""" 线性阶(递归实现) """
|
""" 线性阶(递归实现) """
|
||||||
def linearRecur(n):
|
def linearRecur(n):
|
||||||
print("递归 n = ", n)
|
print("递归 n =", n)
|
||||||
if n == 1: return
|
if n == 1: return
|
||||||
linearRecur(n - 1)
|
linearRecur(n - 1)
|
||||||
|
|
||||||
@ -50,7 +50,7 @@ def quadratic(n):
|
|||||||
def quadratic_recur(n):
|
def quadratic_recur(n):
|
||||||
if n <= 0: return 0
|
if n <= 0: return 0
|
||||||
nums = [0] * n
|
nums = [0] * n
|
||||||
print("递归 n = {} 中的 nums 长度 = {}".format(n, len(nums)))
|
print("递归 n =", n, "中的 nums 长度 =", len(nums))
|
||||||
return quadratic_recur(n - 1)
|
return quadratic_recur(n - 1)
|
||||||
|
|
||||||
""" 指数阶(建立满二叉树) """
|
""" 指数阶(建立满二叉树) """
|
||||||
|
@ -52,6 +52,6 @@ def merge_sort(nums, left, right):
|
|||||||
|
|
||||||
""" Driver Code """
|
""" Driver Code """
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
nums = [4, 1, 3, 1, 5, 2]
|
nums = [ 7, 3, 2, 6, 0, 1, 5, 4 ]
|
||||||
merge_sort(nums, 0, len(nums) - 1)
|
merge_sort(nums, 0, len(nums) - 1)
|
||||||
print("归并排序完成后 nums =", nums)
|
print("归并排序完成后 nums =", nums)
|
||||||
|
@ -56,7 +56,26 @@ comments: true
|
|||||||
=== "C++"
|
=== "C++"
|
||||||
|
|
||||||
```cpp title=""
|
```cpp title=""
|
||||||
|
/* 结构体 */
|
||||||
|
struct Node {
|
||||||
|
int val;
|
||||||
|
Node *next;
|
||||||
|
Node(int x) : val(x), next(nullptr) {}
|
||||||
|
};
|
||||||
|
|
||||||
|
/* 函数(或称方法) */
|
||||||
|
int func() {
|
||||||
|
// do something...
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int algorithm(int n) { // 输入数据
|
||||||
|
const int a = 0; // 暂存数据(常量)
|
||||||
|
int b = 0; // 暂存数据(变量)
|
||||||
|
Node* node = new Node(0); // 暂存数据(对象)
|
||||||
|
int c = func(); // 栈帧空间(调用函数)
|
||||||
|
return a + b + c; // 输出数据
|
||||||
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
=== "Python"
|
=== "Python"
|
||||||
@ -74,7 +93,6 @@ comments: true
|
|||||||
return 0
|
return 0
|
||||||
|
|
||||||
def algorithm(n): # 输入数据
|
def algorithm(n): # 输入数据
|
||||||
a = 0 # 暂存数据(常量)
|
|
||||||
b = 0 # 暂存数据(变量)
|
b = 0 # 暂存数据(变量)
|
||||||
node = Node(0) # 暂存数据(对象)
|
node = Node(0) # 暂存数据(对象)
|
||||||
c = function() # 栈帧空间(调用函数)
|
c = function() # 栈帧空间(调用函数)
|
||||||
@ -104,7 +122,12 @@ comments: true
|
|||||||
=== "C++"
|
=== "C++"
|
||||||
|
|
||||||
```cpp title=""
|
```cpp title=""
|
||||||
|
void algorithm(int n) {
|
||||||
|
int a = 0; // O(1)
|
||||||
|
vector<int> b(10000); // O(1)
|
||||||
|
if (n > 10)
|
||||||
|
vector<int> nums(n); // O(n)
|
||||||
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
=== "Python"
|
=== "Python"
|
||||||
@ -142,7 +165,21 @@ comments: true
|
|||||||
=== "C++"
|
=== "C++"
|
||||||
|
|
||||||
```cpp title=""
|
```cpp title=""
|
||||||
|
int func() {
|
||||||
|
// do something
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
/* 循环 O(1) */
|
||||||
|
void loop(int n) {
|
||||||
|
for (int i = 0; i < n; i++) {
|
||||||
|
func();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/* 递归 O(n) */
|
||||||
|
void recur(int n) {
|
||||||
|
if (n == 1) return;
|
||||||
|
return recur(n - 1);
|
||||||
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
=== "Python"
|
=== "Python"
|
||||||
@ -212,7 +249,22 @@ $$
|
|||||||
=== "C++"
|
=== "C++"
|
||||||
|
|
||||||
```cpp title="space_complexity_types.cpp"
|
```cpp title="space_complexity_types.cpp"
|
||||||
|
/* 常数阶 */
|
||||||
|
void constant(int n) {
|
||||||
|
// 常量、变量、对象占用 O(1) 空间
|
||||||
|
const int a = 0;
|
||||||
|
int b = 0;
|
||||||
|
vector<int> nums(10000);
|
||||||
|
ListNode* node = new ListNode(0);
|
||||||
|
// 循环中的变量占用 O(1) 空间
|
||||||
|
for (int i = 0; i < n; i++) {
|
||||||
|
int c = 0;
|
||||||
|
}
|
||||||
|
// 循环中的函数占用 O(1) 空间
|
||||||
|
for (int i = 0; i < n; i++) {
|
||||||
|
func();
|
||||||
|
}
|
||||||
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
=== "Python"
|
=== "Python"
|
||||||
@ -259,7 +311,21 @@ $$
|
|||||||
=== "C++"
|
=== "C++"
|
||||||
|
|
||||||
```cpp title="space_complexity_types.cpp"
|
```cpp title="space_complexity_types.cpp"
|
||||||
|
/* 线性阶 */
|
||||||
|
void linear(int n) {
|
||||||
|
// 长度为 n 的数组占用 O(n) 空间
|
||||||
|
vector<int> nums(n);
|
||||||
|
// 长度为 n 的列表占用 O(n) 空间
|
||||||
|
vector<ListNode*> nodes;
|
||||||
|
for (int i = 0; i < n; i++) {
|
||||||
|
nodes.push_back(new ListNode(i));
|
||||||
|
}
|
||||||
|
// 长度为 n 的哈希表占用 O(n) 空间
|
||||||
|
unordered_map<int, string> map;
|
||||||
|
for (int i = 0; i < n; i++) {
|
||||||
|
map[i] = to_string(i);
|
||||||
|
}
|
||||||
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
=== "Python"
|
=== "Python"
|
||||||
@ -291,7 +357,12 @@ $$
|
|||||||
=== "C++"
|
=== "C++"
|
||||||
|
|
||||||
```cpp title="space_complexity_types.cpp"
|
```cpp title="space_complexity_types.cpp"
|
||||||
|
/* 线性阶(递归实现) */
|
||||||
|
void linearRecur(int n) {
|
||||||
|
cout << "递归 n = " << n << endl;
|
||||||
|
if (n == 1) return;
|
||||||
|
linearRecur(n - 1);
|
||||||
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
=== "Python"
|
=== "Python"
|
||||||
@ -318,7 +389,7 @@ $$
|
|||||||
/* 平方阶 */
|
/* 平方阶 */
|
||||||
void quadratic(int n) {
|
void quadratic(int n) {
|
||||||
// 矩阵占用 O(n^2) 空间
|
// 矩阵占用 O(n^2) 空间
|
||||||
int numMatrix[][] = new int[n][n];
|
int [][]numMatrix = new int[n][n];
|
||||||
// 二维列表占用 O(n^2) 空间
|
// 二维列表占用 O(n^2) 空间
|
||||||
List<List<Integer>> numList = new ArrayList<>();
|
List<List<Integer>> numList = new ArrayList<>();
|
||||||
for (int i = 0; i < n; i++) {
|
for (int i = 0; i < n; i++) {
|
||||||
@ -334,7 +405,18 @@ $$
|
|||||||
=== "C++"
|
=== "C++"
|
||||||
|
|
||||||
```cpp title="space_complexity_types.cpp"
|
```cpp title="space_complexity_types.cpp"
|
||||||
|
/* 平方阶 */
|
||||||
|
void quadratic(int n) {
|
||||||
|
// 二维列表占用 O(n^2) 空间
|
||||||
|
vector<vector<int>> numMatrix;
|
||||||
|
for (int i = 0; i < n; i++) {
|
||||||
|
vector<int> tmp;
|
||||||
|
for (int j = 0; j < n; j++) {
|
||||||
|
tmp.push_back(0);
|
||||||
|
}
|
||||||
|
numMatrix.push_back(tmp);
|
||||||
|
}
|
||||||
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
=== "Python"
|
=== "Python"
|
||||||
@ -363,7 +445,13 @@ $$
|
|||||||
=== "C++"
|
=== "C++"
|
||||||
|
|
||||||
```cpp title="space_complexity_types.cpp"
|
```cpp title="space_complexity_types.cpp"
|
||||||
|
/* 平方阶(递归实现) */
|
||||||
|
int quadraticRecur(int n) {
|
||||||
|
if (n <= 0) return 0;
|
||||||
|
vector<int> nums(n);
|
||||||
|
cout << "递归 n = " << n << " 中的 nums 长度 = " << nums.size() << endl;
|
||||||
|
return quadraticRecur(n - 1);
|
||||||
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
=== "Python"
|
=== "Python"
|
||||||
@ -401,7 +489,14 @@ $$
|
|||||||
=== "C++"
|
=== "C++"
|
||||||
|
|
||||||
```cpp title="space_complexity_types.cpp"
|
```cpp title="space_complexity_types.cpp"
|
||||||
|
/* 指数阶(建立满二叉树) */
|
||||||
|
TreeNode* buildTree(int n) {
|
||||||
|
if (n == 0) return nullptr;
|
||||||
|
TreeNode* root = new TreeNode(0);
|
||||||
|
root->left = buildTree(n - 1);
|
||||||
|
root->right = buildTree(n - 1);
|
||||||
|
return root;
|
||||||
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
=== "Python"
|
=== "Python"
|
||||||
|
@ -39,7 +39,20 @@ comments: true
|
|||||||
=== "C++"
|
=== "C++"
|
||||||
|
|
||||||
```cpp title="leetcode_two_sum.cpp"
|
```cpp title="leetcode_two_sum.cpp"
|
||||||
|
class SolutionBruteForce {
|
||||||
|
public:
|
||||||
|
vector<int> twoSum(vector<int>& nums, int target) {
|
||||||
|
int size = nums.size();
|
||||||
|
// 两层循环,时间复杂度 O(n^2)
|
||||||
|
for (int i = 0; i < size - 1; i++) {
|
||||||
|
for (int j = i + 1; j < size; j++) {
|
||||||
|
if (nums[i] + nums[j] == target)
|
||||||
|
return { i, j };
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
};
|
||||||
```
|
```
|
||||||
|
|
||||||
=== "Python"
|
=== "Python"
|
||||||
@ -101,7 +114,22 @@ comments: true
|
|||||||
=== "C++"
|
=== "C++"
|
||||||
|
|
||||||
```cpp title="leetcode_two_sum.cpp"
|
```cpp title="leetcode_two_sum.cpp"
|
||||||
|
class SolutionHashMap {
|
||||||
|
public:
|
||||||
|
vector<int> twoSum(vector<int>& nums, int target) {
|
||||||
|
int size = nums.size();
|
||||||
|
// 辅助哈希表,空间复杂度 O(n)
|
||||||
|
unordered_map<int, int> dic;
|
||||||
|
// 单层循环,时间复杂度 O(n)
|
||||||
|
for (int i = 0; i < size; i++) {
|
||||||
|
if (dic.find(target - nums[i]) != dic.end()) {
|
||||||
|
return { dic[target - nums[i]], i };
|
||||||
|
}
|
||||||
|
dic.emplace(nums[i], i);
|
||||||
|
}
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
};
|
||||||
```
|
```
|
||||||
|
|
||||||
=== "Python"
|
=== "Python"
|
||||||
|
@ -36,7 +36,16 @@ $$
|
|||||||
=== "C++"
|
=== "C++"
|
||||||
|
|
||||||
```cpp title=""
|
```cpp title=""
|
||||||
|
// 在某运行平台下
|
||||||
|
void algorithm(int n) {
|
||||||
|
int a = 2; // 1 ns
|
||||||
|
a = a + 1; // 1 ns
|
||||||
|
a = a * 2; // 10 ns
|
||||||
|
// 循环 n 次
|
||||||
|
for (int i = 0; i < n; i++) { // 1 ns ,每轮都要执行 i++
|
||||||
|
cout << 0 << endl; // 5 ns
|
||||||
|
}
|
||||||
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
=== "Python"
|
=== "Python"
|
||||||
@ -88,7 +97,22 @@ $$
|
|||||||
=== "C++"
|
=== "C++"
|
||||||
|
|
||||||
```cpp title=""
|
```cpp title=""
|
||||||
|
// 算法 A 时间复杂度:常数阶
|
||||||
|
void algorithm_A(int n) {
|
||||||
|
cout << 0 << endl;
|
||||||
|
}
|
||||||
|
// 算法 B 时间复杂度:线性阶
|
||||||
|
void algorithm_B(int n) {
|
||||||
|
for (int i = 0; i < n; i++) {
|
||||||
|
cout << 0 << endl;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// 算法 C 时间复杂度:常数阶
|
||||||
|
void algorithm_C(int n) {
|
||||||
|
for (int i = 0; i < 1000000; i++) {
|
||||||
|
cout << 0 << endl;
|
||||||
|
}
|
||||||
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
=== "Python"
|
=== "Python"
|
||||||
@ -144,7 +168,15 @@ $$
|
|||||||
=== "C++"
|
=== "C++"
|
||||||
|
|
||||||
```cpp title=""
|
```cpp title=""
|
||||||
|
void algorithm(int n) {
|
||||||
|
int a = 1; // +1
|
||||||
|
a = a + 1; // +1
|
||||||
|
a = a * 2; // +1
|
||||||
|
// 循环 n 次
|
||||||
|
for (int i = 0; i < n; i++) { // +1(每轮都执行 i ++)
|
||||||
|
cout << 0 << endl; // +1
|
||||||
|
}
|
||||||
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
=== "Python"
|
=== "Python"
|
||||||
@ -233,7 +265,20 @@ $$
|
|||||||
=== "C++"
|
=== "C++"
|
||||||
|
|
||||||
```cpp title=""
|
```cpp title=""
|
||||||
|
void algorithm(int n) {
|
||||||
|
int a = 1; // +0(技巧 1)
|
||||||
|
a = a + n; // +0(技巧 1)
|
||||||
|
// +n(技巧 2)
|
||||||
|
for (int i = 0; i < 5 * n + 1; i++) {
|
||||||
|
cout << 0 << endl;
|
||||||
|
}
|
||||||
|
// +n*n(技巧 3)
|
||||||
|
for (int i = 0; i < 2 * n; i++) {
|
||||||
|
for (int j = 0; j < n + 1; j++) {
|
||||||
|
cout << 0 << endl;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
=== "Python"
|
=== "Python"
|
||||||
@ -310,7 +355,14 @@ $$
|
|||||||
=== "C++"
|
=== "C++"
|
||||||
|
|
||||||
```cpp title="time_complexity_types.cpp"
|
```cpp title="time_complexity_types.cpp"
|
||||||
|
/* 常数阶 */
|
||||||
|
int constant(int n) {
|
||||||
|
int count = 0;
|
||||||
|
int size = 100000;
|
||||||
|
for (int i = 0; i < size; i++)
|
||||||
|
count++;
|
||||||
|
return count;
|
||||||
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
=== "Python"
|
=== "Python"
|
||||||
@ -344,7 +396,13 @@ $$
|
|||||||
=== "C++"
|
=== "C++"
|
||||||
|
|
||||||
```cpp title="time_complexity_types.cpp"
|
```cpp title="time_complexity_types.cpp"
|
||||||
|
/* 线性阶 */
|
||||||
|
int linear(int n) {
|
||||||
|
int count = 0;
|
||||||
|
for (int i = 0; i < n; i++)
|
||||||
|
count++;
|
||||||
|
return count;
|
||||||
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
=== "Python"
|
=== "Python"
|
||||||
@ -381,7 +439,15 @@ $$
|
|||||||
=== "C++"
|
=== "C++"
|
||||||
|
|
||||||
```cpp title="time_complexity_types.cpp"
|
```cpp title="time_complexity_types.cpp"
|
||||||
|
/* 线性阶(遍历数组) */
|
||||||
|
int arrayTraversal(vector<int>& nums) {
|
||||||
|
int count = 0;
|
||||||
|
// 循环次数与数组长度成正比
|
||||||
|
for (int num : nums) {
|
||||||
|
count++;
|
||||||
|
}
|
||||||
|
return count;
|
||||||
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
=== "Python"
|
=== "Python"
|
||||||
@ -419,7 +485,17 @@ $$
|
|||||||
=== "C++"
|
=== "C++"
|
||||||
|
|
||||||
```cpp title="time_complexity_types.cpp"
|
```cpp title="time_complexity_types.cpp"
|
||||||
|
/* 平方阶 */
|
||||||
|
int quadratic(int n) {
|
||||||
|
int count = 0;
|
||||||
|
// 循环次数与数组长度成平方关系
|
||||||
|
for (int i = 0; i < n; i++) {
|
||||||
|
for (int j = 0; j < n; j++) {
|
||||||
|
count++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return count;
|
||||||
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
=== "Python"
|
=== "Python"
|
||||||
@ -471,7 +547,24 @@ $$
|
|||||||
=== "C++"
|
=== "C++"
|
||||||
|
|
||||||
```cpp title="time_complexity_types.cpp"
|
```cpp title="time_complexity_types.cpp"
|
||||||
|
/* 平方阶(冒泡排序) */
|
||||||
|
int bubbleSort(vector<int>& nums) {
|
||||||
|
int count = 0; // 计数器
|
||||||
|
// 外循环:待排序元素数量为 n-1, n-2, ..., 1
|
||||||
|
for (int i = nums.size() - 1; i > 0; i--) {
|
||||||
|
// 内循环:冒泡操作
|
||||||
|
for (int j = 0; j < i; j++) {
|
||||||
|
if (nums[j] > nums[j + 1]) {
|
||||||
|
// 交换 nums[j] 与 nums[j + 1]
|
||||||
|
int tmp = nums[j];
|
||||||
|
nums[j] = nums[j + 1];
|
||||||
|
nums[j + 1] = tmp;
|
||||||
|
count += 3; // 元素交换包含 3 个单元操作
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return count;
|
||||||
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
=== "Python"
|
=== "Python"
|
||||||
@ -522,7 +615,19 @@ $$
|
|||||||
=== "C++"
|
=== "C++"
|
||||||
|
|
||||||
```cpp title="time_complexity_types.cpp"
|
```cpp title="time_complexity_types.cpp"
|
||||||
|
/* 指数阶(循环实现) */
|
||||||
|
int exponential(int n) {
|
||||||
|
int count = 0, base = 1;
|
||||||
|
// cell 每轮一分为二,形成数列 1, 2, 4, 8, ..., 2^(n-1)
|
||||||
|
for (int i = 0; i < n; i++) {
|
||||||
|
for (int j = 0; j < base; j++) {
|
||||||
|
count++;
|
||||||
|
}
|
||||||
|
base *= 2;
|
||||||
|
}
|
||||||
|
// count = 1 + 2 + 4 + 8 + .. + 2^(n-1) = 2^n - 1
|
||||||
|
return count;
|
||||||
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
=== "Python"
|
=== "Python"
|
||||||
@ -559,7 +664,11 @@ $$
|
|||||||
=== "C++"
|
=== "C++"
|
||||||
|
|
||||||
```cpp title="time_complexity_types.cpp"
|
```cpp title="time_complexity_types.cpp"
|
||||||
|
/* 指数阶(递归实现) */
|
||||||
|
int expRecur(int n) {
|
||||||
|
if (n == 1) return 1;
|
||||||
|
return expRecur(n - 1) + expRecur(n - 1) + 1;
|
||||||
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
=== "Python"
|
=== "Python"
|
||||||
@ -596,7 +705,15 @@ $$
|
|||||||
=== "C++"
|
=== "C++"
|
||||||
|
|
||||||
```cpp title="time_complexity_types.cpp"
|
```cpp title="time_complexity_types.cpp"
|
||||||
|
/* 对数阶(循环实现) */
|
||||||
|
int logarithmic(float n) {
|
||||||
|
int count = 0;
|
||||||
|
while (n > 1) {
|
||||||
|
n = n / 2;
|
||||||
|
count++;
|
||||||
|
}
|
||||||
|
return count;
|
||||||
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
=== "Python"
|
=== "Python"
|
||||||
@ -630,7 +747,11 @@ $$
|
|||||||
=== "C++"
|
=== "C++"
|
||||||
|
|
||||||
```cpp title="time_complexity_types.cpp"
|
```cpp title="time_complexity_types.cpp"
|
||||||
|
/* 对数阶(递归实现) */
|
||||||
|
int logRecur(float n) {
|
||||||
|
if (n <= 1) return 0;
|
||||||
|
return logRecur(n / 2) + 1;
|
||||||
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
=== "Python"
|
=== "Python"
|
||||||
@ -666,7 +787,16 @@ $$
|
|||||||
=== "C++"
|
=== "C++"
|
||||||
|
|
||||||
```cpp title="time_complexity_types.cpp"
|
```cpp title="time_complexity_types.cpp"
|
||||||
|
/* 线性对数阶 */
|
||||||
|
int linearLogRecur(float n) {
|
||||||
|
if (n <= 1) return 1;
|
||||||
|
int count = linearLogRecur(n / 2) +
|
||||||
|
linearLogRecur(n / 2);
|
||||||
|
for (int i = 0; i < n; i++) {
|
||||||
|
count++;
|
||||||
|
}
|
||||||
|
return count;
|
||||||
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
=== "Python"
|
=== "Python"
|
||||||
@ -714,7 +844,16 @@ $$
|
|||||||
=== "C++"
|
=== "C++"
|
||||||
|
|
||||||
```cpp title="time_complexity_types.cpp"
|
```cpp title="time_complexity_types.cpp"
|
||||||
|
/* 阶乘阶(递归实现) */
|
||||||
|
int factorialRecur(int n) {
|
||||||
|
if (n == 0) return 1;
|
||||||
|
int count = 0;
|
||||||
|
// 从 1 个分裂出 n 个
|
||||||
|
for (int i = 0; i < n; i++) {
|
||||||
|
count += factorialRecur(n - 1);
|
||||||
|
}
|
||||||
|
return count;
|
||||||
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
=== "Python"
|
=== "Python"
|
||||||
@ -789,7 +928,42 @@ $$
|
|||||||
=== "C++"
|
=== "C++"
|
||||||
|
|
||||||
```cpp title="worst_best_time_complexity.cpp"
|
```cpp title="worst_best_time_complexity.cpp"
|
||||||
|
/* 生成一个数组,元素为 { 1, 2, ..., n },顺序被打乱 */
|
||||||
|
vector<int> randomNumbers(int n) {
|
||||||
|
vector<int> nums(n);
|
||||||
|
// 生成数组 nums = { 1, 2, 3, ..., n }
|
||||||
|
for (int i = 0; i < n; i++) {
|
||||||
|
nums[i] = i + 1;
|
||||||
|
}
|
||||||
|
// 使用系统时间生成随机种子
|
||||||
|
unsigned seed = chrono::system_clock::now().time_since_epoch().count();
|
||||||
|
// 随机打乱数组元素
|
||||||
|
shuffle(nums.begin(), nums.end(), default_random_engine(seed));
|
||||||
|
return nums;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 查找数组 nums 中数字 1 所在索引 */
|
||||||
|
int findOne(vector<int>& nums) {
|
||||||
|
for (int i = 0; i < nums.size(); i++) {
|
||||||
|
if (nums[i] == 1)
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* Driver Code */
|
||||||
|
int main() {
|
||||||
|
for (int i = 0; i < 1000; i++) {
|
||||||
|
int n = 100;
|
||||||
|
vector<int> nums = randomNumbers(n);
|
||||||
|
int index = findOne(nums);
|
||||||
|
cout << "\n数组 [ 1, 2, ..., n ] 被打乱后 = ";
|
||||||
|
PrintUtil::printVector(nums);
|
||||||
|
cout << "数字 1 的索引为 " << index << endl;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
=== "Python"
|
=== "Python"
|
||||||
|
@ -80,6 +80,28 @@ $$
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
=== "C++"
|
||||||
|
|
||||||
|
```cpp title="binary_search.cpp"
|
||||||
|
/* 二分查找(双闭区间) */
|
||||||
|
int binarySearch(vector<int>& nums, int target) {
|
||||||
|
// 初始化双闭区间 [0, n-1] ,即 i, j 分别指向数组首元素、尾元素
|
||||||
|
int i = 0, j = nums.size() - 1;
|
||||||
|
// 循环,当搜索区间为空时跳出(当 i > j 时为空)
|
||||||
|
while (i <= j) {
|
||||||
|
int m = (i + j) / 2; // 计算中点索引 m
|
||||||
|
if (nums[m] < target) // 此情况说明 target 在区间 [m+1, j] 中
|
||||||
|
i = m + 1;
|
||||||
|
else if (nums[m] > target) // 此情况说明 target 在区间 [i, m-1] 中
|
||||||
|
j = m - 1;
|
||||||
|
else // 找到目标元素,返回其索引
|
||||||
|
return m;
|
||||||
|
}
|
||||||
|
// 未找到目标元素,返回 -1
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
### “左闭右开” 实现
|
### “左闭右开” 实现
|
||||||
|
|
||||||
当然,我们也可以使用 “左闭右开” 的表示方法,写出相同功能的二分查找代码。
|
当然,我们也可以使用 “左闭右开” 的表示方法,写出相同功能的二分查找代码。
|
||||||
@ -106,6 +128,28 @@ $$
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
=== "C++"
|
||||||
|
|
||||||
|
```cpp title="binary_search.cpp"
|
||||||
|
/* 二分查找(左闭右开) */
|
||||||
|
int binarySearch1(vector<int>& nums, int target) {
|
||||||
|
// 初始化左闭右开 [0, n) ,即 i, j 分别指向数组首元素、尾元素+1
|
||||||
|
int i = 0, j = nums.size();
|
||||||
|
// 循环,当搜索区间为空时跳出(当 i = j 时为空)
|
||||||
|
while (i < j) {
|
||||||
|
int m = (i + j) / 2; // 计算中点索引 m
|
||||||
|
if (nums[m] < target) // 此情况说明 target 在区间 [m+1, j) 中
|
||||||
|
i = m + 1;
|
||||||
|
else if (nums[m] > target) // 此情况说明 target 在区间 [i, m) 中
|
||||||
|
j = m;
|
||||||
|
else // 找到目标元素,返回其索引
|
||||||
|
return m;
|
||||||
|
}
|
||||||
|
// 未找到目标元素,返回 -1
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
### 两种表示对比
|
### 两种表示对比
|
||||||
|
|
||||||
对比下来,两种表示的代码写法有以下不同点:
|
对比下来,两种表示的代码写法有以下不同点:
|
||||||
@ -148,7 +192,5 @@ int m = i + (j - i) / 2;
|
|||||||
但并不意味着所有情况下都应使用二分查找,这是因为:
|
但并不意味着所有情况下都应使用二分查找,这是因为:
|
||||||
|
|
||||||
- **二分查找仅适用于有序数据。** 如果输入数据是乱序的,为了使用二分查找而专门执行数据排序,那么是得不偿失的,因为排序算法的时间复杂度一般为 $O(n \log n)$ ,比线性查找和二分查找都更差。再例如,对于频繁插入元素的场景,为了保持数组的有序性,需要将元素插入到特定位置,时间复杂度为 $O(n)$ ,也是非常昂贵的。
|
- **二分查找仅适用于有序数据。** 如果输入数据是乱序的,为了使用二分查找而专门执行数据排序,那么是得不偿失的,因为排序算法的时间复杂度一般为 $O(n \log n)$ ,比线性查找和二分查找都更差。再例如,对于频繁插入元素的场景,为了保持数组的有序性,需要将元素插入到特定位置,时间复杂度为 $O(n)$ ,也是非常昂贵的。
|
||||||
|
|
||||||
- **二分查找仅适用于数组。** 由于在二分查找中,访问索引是 ”非连续“ 的,因此链表或者基于链表实现的数据结构都无法使用。
|
- **二分查找仅适用于数组。** 由于在二分查找中,访问索引是 ”非连续“ 的,因此链表或者基于链表实现的数据结构都无法使用。
|
||||||
|
|
||||||
- **在小数据量下,线性查找的性能更好。** 在线性查找中,每轮只需要 1 次判断操作;而在二分查找中,需要 1 次加法、1 次除法、1 ~ 3 次判断操作、1 次加法(减法),共 4 ~ 6 个单元操作;因此,在数据量 $n$ 较小时,线性查找反而比二分查找更快。
|
- **在小数据量下,线性查找的性能更好。** 在线性查找中,每轮只需要 1 次判断操作;而在二分查找中,需要 1 次加法、1 次除法、1 ~ 3 次判断操作、1 次加法(减法),共 4 ~ 6 个单元操作;因此,在数据量 $n$ 较小时,线性查找反而比二分查找更快。
|
||||||
|
@ -4,7 +4,7 @@ comments: true
|
|||||||
|
|
||||||
# 哈希查找
|
# 哈希查找
|
||||||
|
|
||||||
!!! question
|
!!! question
|
||||||
|
|
||||||
在数据量很大时,「线性查找」太慢;而「二分查找」要求数据必须是有序的,并且只能在数组中应用。那么是否有方法可以同时避免上述缺点呢?答案是肯定的,此方法被称为「哈希查找」。
|
在数据量很大时,「线性查找」太慢;而「二分查找」要求数据必须是有序的,并且只能在数组中应用。那么是否有方法可以同时避免上述缺点呢?答案是肯定的,此方法被称为「哈希查找」。
|
||||||
|
|
||||||
@ -27,6 +27,19 @@ comments: true
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
=== "C++"
|
||||||
|
|
||||||
|
```cpp title="hashing_search.cpp"
|
||||||
|
/* 哈希查找(数组) */
|
||||||
|
int hashingSearch(unordered_map<int, int> map, int target) {
|
||||||
|
// 哈希表的 key: 目标元素,value: 索引
|
||||||
|
// 若哈希表中无此 key ,返回 -1
|
||||||
|
if (map.find(target) == map.end())
|
||||||
|
return -1;
|
||||||
|
return map[target];
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
再比如,如果我们想要给定一个目标结点值 `target` ,获取对应的链表结点对象,那么也可以使用哈希查找实现。
|
再比如,如果我们想要给定一个目标结点值 `target` ,获取对应的链表结点对象,那么也可以使用哈希查找实现。
|
||||||
|
|
||||||
![hash_search_listnode](hashing_search.assets/hash_search_listnode.png)
|
![hash_search_listnode](hashing_search.assets/hash_search_listnode.png)
|
||||||
@ -37,11 +50,24 @@ comments: true
|
|||||||
/* 哈希查找(链表) */
|
/* 哈希查找(链表) */
|
||||||
ListNode hashingSearch1(Map<Integer, ListNode> map, int target) {
|
ListNode hashingSearch1(Map<Integer, ListNode> map, int target) {
|
||||||
// 哈希表的 key: 目标结点值,value: 结点对象
|
// 哈希表的 key: 目标结点值,value: 结点对象
|
||||||
// 若哈希表中无此 key ,返回 -1
|
// 若哈希表中无此 key ,返回 null
|
||||||
return map.getOrDefault(target, null);
|
return map.getOrDefault(target, null);
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
=== "C++"
|
||||||
|
|
||||||
|
```cpp title="hashing_search.cpp"
|
||||||
|
/* 哈希查找(链表) */
|
||||||
|
ListNode* hashingSearch1(unordered_map<int, ListNode*> map, int target) {
|
||||||
|
// 哈希表的 key: 目标结点值,value: 结点对象
|
||||||
|
// 若哈希表中无此 key ,返回 nullptr
|
||||||
|
if (map.find(target) == map.end())
|
||||||
|
return nullptr;
|
||||||
|
return map[target];
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
## 复杂度分析
|
## 复杂度分析
|
||||||
|
|
||||||
**时间复杂度:** $O(1)$ ,哈希表的查找操作使用 $O(1)$ 时间。
|
**时间复杂度:** $O(1)$ ,哈希表的查找操作使用 $O(1)$ 时间。
|
||||||
|
@ -28,6 +28,22 @@ comments: true
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
=== "C++"
|
||||||
|
|
||||||
|
```cpp title="linear_search.cpp"
|
||||||
|
/* 线性查找(数组) */
|
||||||
|
int linearSearch(vector<int>& nums, int target) {
|
||||||
|
// 遍历数组
|
||||||
|
for (int i = 0; i < nums.size(); i++) {
|
||||||
|
// 找到目标元素,返回其索引
|
||||||
|
if (nums[i] == target)
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
// 未找到目标元素,返回 -1
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
再比如,我们想要在给定一个目标结点值 `target` ,返回此结点对象,也可以在链表中进行线性查找。
|
再比如,我们想要在给定一个目标结点值 `target` ,返回此结点对象,也可以在链表中进行线性查找。
|
||||||
|
|
||||||
=== "Java"
|
=== "Java"
|
||||||
@ -47,6 +63,23 @@ comments: true
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
=== "C++"
|
||||||
|
|
||||||
|
```cpp title="linear_search.cpp"
|
||||||
|
/* 线性查找(链表) */
|
||||||
|
ListNode* linearSearch(ListNode* head, int target) {
|
||||||
|
// 遍历链表
|
||||||
|
while (head != nullptr) {
|
||||||
|
// 找到目标结点,返回之
|
||||||
|
if (head->val == target)
|
||||||
|
return head;
|
||||||
|
head = head->next;
|
||||||
|
}
|
||||||
|
// 未找到目标结点,返回 nullptr
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
## 复杂度分析
|
## 复杂度分析
|
||||||
|
|
||||||
**时间复杂度 $O(n)$ :** 其中 $n$ 为数组或链表长度。
|
**时间复杂度 $O(n)$ :** 其中 $n$ 为数组或链表长度。
|
||||||
|
@ -56,7 +56,7 @@ comments: true
|
|||||||
|
|
||||||
=== "Java"
|
=== "Java"
|
||||||
|
|
||||||
```java
|
```java title="bubble_sort.java"
|
||||||
/* 冒泡排序 */
|
/* 冒泡排序 */
|
||||||
void bubbleSort(int[] nums) {
|
void bubbleSort(int[] nums) {
|
||||||
// 外循环:待排序元素数量为 n-1, n-2, ..., 1
|
// 外循环:待排序元素数量为 n-1, n-2, ..., 1
|
||||||
@ -73,10 +73,29 @@ comments: true
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
=== "C++"
|
||||||
|
|
||||||
|
```cpp title="bubble_sort.cpp"
|
||||||
|
/* 冒泡排序 */
|
||||||
|
void bubbleSort(vector<int>& nums) {
|
||||||
|
// 外循环:待排序元素数量为 n-1, n-2, ..., 1
|
||||||
|
for (int i = nums.size() - 1; i > 0; i--) {
|
||||||
|
// 内循环:冒泡操作
|
||||||
|
for (int j = 0; j < i; j++) {
|
||||||
|
if (nums[j] > nums[j + 1]) {
|
||||||
|
// 交换 nums[j] 与 nums[j + 1]
|
||||||
|
int tmp = nums[j];
|
||||||
|
nums[j] = nums[j + 1];
|
||||||
|
nums[j + 1] = tmp;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
=== "Python"
|
=== "Python"
|
||||||
|
|
||||||
```python
|
```python title="bubble_sort.py"
|
||||||
""" 冒泡排序 """
|
""" 冒泡排序 """
|
||||||
def bubble_sort(nums):
|
def bubble_sort(nums):
|
||||||
n = len(nums)
|
n = len(nums)
|
||||||
@ -109,7 +128,7 @@ comments: true
|
|||||||
|
|
||||||
=== "Java"
|
=== "Java"
|
||||||
|
|
||||||
```java
|
```java title="bubble_sort.java"
|
||||||
/* 冒泡排序(标志优化)*/
|
/* 冒泡排序(标志优化)*/
|
||||||
void bubbleSortWithFlag(int[] nums) {
|
void bubbleSortWithFlag(int[] nums) {
|
||||||
// 外循环:待排序元素数量为 n-1, n-2, ..., 1
|
// 外循环:待排序元素数量为 n-1, n-2, ..., 1
|
||||||
@ -130,9 +149,32 @@ comments: true
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
=== "C++"
|
||||||
|
|
||||||
|
```cpp title="bubble_sort.cpp"
|
||||||
|
/* 冒泡排序(标志优化)*/
|
||||||
|
void bubbleSortWithFlag(vector<int>& nums) {
|
||||||
|
// 外循环:待排序元素数量为 n-1, n-2, ..., 1
|
||||||
|
for (int i = nums.size() - 1; i > 0; i--) {
|
||||||
|
bool flag = false; // 初始化标志位
|
||||||
|
// 内循环:冒泡操作
|
||||||
|
for (int j = 0; j < i; j++) {
|
||||||
|
if (nums[j] > nums[j + 1]) {
|
||||||
|
// 交换 nums[j] 与 nums[j + 1]
|
||||||
|
int tmp = nums[j];
|
||||||
|
nums[j] = nums[j + 1];
|
||||||
|
nums[j + 1] = tmp;
|
||||||
|
flag = true; // 记录交换元素
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!flag) break; // 此轮冒泡未交换任何元素,直接跳出
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
=== "Python"
|
=== "Python"
|
||||||
|
|
||||||
```python
|
```python title="bubble_sort.py"
|
||||||
""" 冒泡排序(标志优化) """
|
""" 冒泡排序(标志优化) """
|
||||||
def bubble_sort_with_flag(nums):
|
def bubble_sort_with_flag(nums):
|
||||||
n = len(nums)
|
n = len(nums)
|
||||||
|
@ -17,9 +17,7 @@ comments: true
|
|||||||
## 算法流程
|
## 算法流程
|
||||||
|
|
||||||
1. 第 1 轮先选取数组的 **第 2 个元素** 为 `base` ,执行「插入操作」后, **数组前 2 个元素已完成排序**。
|
1. 第 1 轮先选取数组的 **第 2 个元素** 为 `base` ,执行「插入操作」后, **数组前 2 个元素已完成排序**。
|
||||||
|
|
||||||
2. 第 2 轮选取 **第 3 个元素** 为 `base` ,执行「插入操作」后, **数组前 3 个元素已完成排序**。
|
2. 第 2 轮选取 **第 3 个元素** 为 `base` ,执行「插入操作」后, **数组前 3 个元素已完成排序**。
|
||||||
|
|
||||||
3. 以此类推……最后一轮选取 **数组尾元素** 为 `base` ,执行「插入操作」后 **所有元素已完成排序**。
|
3. 以此类推……最后一轮选取 **数组尾元素** 为 `base` ,执行「插入操作」后 **所有元素已完成排序**。
|
||||||
|
|
||||||
![insertion_sort](insertion_sort.assets/insertion_sort.png)
|
![insertion_sort](insertion_sort.assets/insertion_sort.png)
|
||||||
@ -28,7 +26,7 @@ comments: true
|
|||||||
|
|
||||||
=== "Java"
|
=== "Java"
|
||||||
|
|
||||||
```java
|
```java title="insertion_sort.java"
|
||||||
/* 插入排序 */
|
/* 插入排序 */
|
||||||
void insertionSort(int[] nums) {
|
void insertionSort(int[] nums) {
|
||||||
// 外循环:base = nums[1], nums[2], ..., nums[n-1]
|
// 外循环:base = nums[1], nums[2], ..., nums[n-1]
|
||||||
@ -44,9 +42,27 @@ comments: true
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
=== "C++"
|
||||||
|
|
||||||
|
```cpp title="insertion_sort.cpp"
|
||||||
|
/* 插入排序 */
|
||||||
|
void insertionSort(vector<int>& nums) {
|
||||||
|
// 外循环:base = nums[1], nums[2], ..., nums[n-1]
|
||||||
|
for (int i = 1; i < nums.size(); i++) {
|
||||||
|
int base = nums[i], j = i - 1;
|
||||||
|
// 内循环:将 base 插入到左边的正确位置
|
||||||
|
while (j >= 0 && nums[j] > base) {
|
||||||
|
nums[j + 1] = nums[j]; // 1. 将 nums[j] 向右移动一位
|
||||||
|
j--;
|
||||||
|
}
|
||||||
|
nums[j + 1] = base; // 2. 将 base 赋值到正确位置
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
=== "Python"
|
=== "Python"
|
||||||
|
|
||||||
```python
|
```python title="insertion_sort.py"
|
||||||
""" 插入排序 """
|
""" 插入排序 """
|
||||||
def insertion_sort(nums):
|
def insertion_sort(nums):
|
||||||
# 外循环:base = nums[1], nums[2], ..., nums[n-1]
|
# 外循环:base = nums[1], nums[2], ..., nums[n-1]
|
||||||
|
@ -103,6 +103,50 @@ comments: true
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
=== "C++"
|
||||||
|
|
||||||
|
```cpp title="merge_sort.cpp"
|
||||||
|
/**
|
||||||
|
* 合并左子数组和右子数组
|
||||||
|
* 左子数组区间 [left, mid]
|
||||||
|
* 右子数组区间 [mid + 1, right]
|
||||||
|
*/
|
||||||
|
void merge(vector<int>& nums, int left, int mid, int right) {
|
||||||
|
// 初始化辅助数组
|
||||||
|
vector<int> tmp(nums.begin() + left, nums.begin() + right + 1);
|
||||||
|
// 左子数组的起始索引和结束索引
|
||||||
|
int leftStart = left - left, leftEnd = mid - left;
|
||||||
|
// 右子数组的起始索引和结束索引
|
||||||
|
int rightStart = mid + 1 - left, rightEnd = right - left;
|
||||||
|
// i, j 分别指向左子数组、右子数组的首元素
|
||||||
|
int i = leftStart, j = rightStart;
|
||||||
|
// 通过覆盖原数组 nums 来合并左子数组和右子数组
|
||||||
|
for (int k = left; k <= right; k++) {
|
||||||
|
// 若 “左子数组已全部合并完”,则选取右子数组元素,并且 j++
|
||||||
|
if (i > leftEnd)
|
||||||
|
nums[k] = tmp[j++];
|
||||||
|
// 否则,若 “右子数组已全部合并完” 或 “左子数组元素 < 右子数组元素”,则选取左子数组元素,并且 i++
|
||||||
|
else if (j > rightEnd || tmp[i] <= tmp[j])
|
||||||
|
nums[k] = tmp[i++];
|
||||||
|
// 否则,若 “左子数组元素 > 右子数组元素”,则选取右子数组元素,并且 j++
|
||||||
|
else
|
||||||
|
nums[k] = tmp[j++];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 归并排序 */
|
||||||
|
void mergeSort(vector<int>& nums, int left, int right) {
|
||||||
|
// 终止条件
|
||||||
|
if (left >= right) return; // 当子数组长度为 1 时终止递归
|
||||||
|
// 划分阶段
|
||||||
|
int mid = (left + right) / 2; // 计算中点
|
||||||
|
mergeSort(nums, left, mid); // 递归左子数组
|
||||||
|
mergeSort(nums, mid + 1, right); // 递归右子数组
|
||||||
|
// 合并阶段
|
||||||
|
merge(nums, left, mid, right);
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
=== "Python"
|
=== "Python"
|
||||||
|
|
||||||
```python title="merge_sort.py"
|
```python title="merge_sort.py"
|
||||||
|
@ -61,6 +61,32 @@ comments: true
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
=== "C++"
|
||||||
|
|
||||||
|
```cpp title="quick_sort.cpp"
|
||||||
|
/* 元素交换 */
|
||||||
|
void swap(vector<int>& nums, int i, int j) {
|
||||||
|
int tmp = nums[i];
|
||||||
|
nums[i] = nums[j];
|
||||||
|
nums[j] = tmp;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 哨兵划分 */
|
||||||
|
int partition(vector<int>& nums, int left, int right) {
|
||||||
|
// 以 nums[left] 作为基准数
|
||||||
|
int i = left, j = right;
|
||||||
|
while (i < j) {
|
||||||
|
while (i < j && nums[j] >= nums[left])
|
||||||
|
j--; // 从右向左找首个小于基准数的元素
|
||||||
|
while (i < j && nums[i] <= nums[left])
|
||||||
|
i++; // 从左向右找首个大于基准数的元素
|
||||||
|
swap(nums, i, j); // 交换这两个元素
|
||||||
|
}
|
||||||
|
swap(nums, i, left); // 将基准数交换至两子数组的分界线
|
||||||
|
return i; // 返回基准数的索引
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
=== "Python"
|
=== "Python"
|
||||||
|
|
||||||
```python title="quick_sort.py"
|
```python title="quick_sort.py"
|
||||||
@ -112,6 +138,22 @@ comments: true
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
=== "C++"
|
||||||
|
|
||||||
|
```cpp title="quick_sort.cpp"
|
||||||
|
/* 快速排序 */
|
||||||
|
static void quickSort(vector<int>& nums, int left, int right) {
|
||||||
|
// 子数组长度为 1 时终止递归
|
||||||
|
if (left >= right)
|
||||||
|
return;
|
||||||
|
// 哨兵划分
|
||||||
|
int pivot = partition(nums, left, right);
|
||||||
|
// 递归左子数组、右子数组
|
||||||
|
quickSort(nums, left, pivot - 1);
|
||||||
|
quickSort(nums, pivot + 1, right);
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
=== "Python"
|
=== "Python"
|
||||||
|
|
||||||
```python title="quick_sort.py"
|
```python title="quick_sort.py"
|
||||||
@ -183,6 +225,32 @@ comments: true
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
=== "C++"
|
||||||
|
|
||||||
|
```cpp title="quick_sort.cpp"
|
||||||
|
/* 选取三个元素的中位数 */
|
||||||
|
int medianThree(vector<int>& nums, int left, int mid, int right) {
|
||||||
|
// 使用了异或操作来简化代码
|
||||||
|
// 异或规则为 0 ^ 0 = 1 ^ 1 = 0, 0 ^ 1 = 1 ^ 0 = 1
|
||||||
|
if ((nums[left] > nums[mid]) ^ (nums[left] > nums[right]))
|
||||||
|
return left;
|
||||||
|
else if ((nums[mid] < nums[left]) ^ (nums[mid] < nums[right]))
|
||||||
|
return mid;
|
||||||
|
else
|
||||||
|
return right;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 哨兵划分(三数取中值) */
|
||||||
|
int partition(vector<int>& nums, int left, int right) {
|
||||||
|
// 选取三个候选元素的中位数
|
||||||
|
int med = medianThree(nums, left, (left + right) / 2, right);
|
||||||
|
// 将中位数交换至数组最左端
|
||||||
|
swap(nums, left, med);
|
||||||
|
// 以 nums[left] 作为基准数
|
||||||
|
// 下同省略...
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
=== "Python"
|
=== "Python"
|
||||||
|
|
||||||
```python title="quick_sort.py"
|
```python title="quick_sort.py"
|
||||||
@ -233,6 +301,27 @@ comments: true
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
=== "C++"
|
||||||
|
|
||||||
|
```cpp title="quick_sort.cpp"
|
||||||
|
/* 快速排序(尾递归优化) */
|
||||||
|
static void quickSort(vector<int>& nums, int left, int right) {
|
||||||
|
// 子数组长度为 1 时终止
|
||||||
|
while (left < right) {
|
||||||
|
// 哨兵划分操作
|
||||||
|
int pivot = partition(nums, left, right);
|
||||||
|
// 对两个子数组中较短的那个执行快排
|
||||||
|
if (pivot - left < right - pivot) {
|
||||||
|
quickSort(nums, left, pivot - 1); // 递归排序左子数组
|
||||||
|
left = pivot + 1; // 剩余待排序区间为 [pivot + 1, right]
|
||||||
|
} else {
|
||||||
|
quickSort(nums, pivot + 1, right); // 递归排序右子数组
|
||||||
|
right = pivot - 1; // 剩余待排序区间为 [left, pivot - 1]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
=== "Python"
|
=== "Python"
|
||||||
|
|
||||||
```python title="quick_sort.py"
|
```python title="quick_sort.py"
|
||||||
|
Loading…
Reference in New Issue
Block a user