【左程云算法全讲3】归并排序与随机快排

news/2024/11/8 11:56:40/

系列综述:
💞目的:本系列是个人整理为了秋招面试的,整理期间苛求每个知识点,平衡理解简易度与深入程度。
🥰来源:材料主要源于左程云算法课程进行的,每个知识点的修正和深入主要参考各平台大佬的文章,其中也可能含有少量的个人实验自证。
🤭结语:如果有帮到你的地方,就点个赞关注一下呗,谢谢🎈🎄🌷!!!
🌈【C++】秋招&实习面经汇总篇


文章目录

      • 归并排序
      • 快速排序
    • 参考博客


😊点此到文末惊喜↩︎

归并排序

  1. 是否可递归:大问题能否通过范围缩小但是同等定义的子问题搞定
  2. 归并排序
// 将两个数组从小到大合并成为一个
void Merge(vector<int> &vec, int L, int mid, int R) {const int n = R-L+1;vector<int> tmp(n, 0);  // 注意长度int i = 0;      // 工作指针int p1 = L;     // 左半部分的工作指针int p2 = mid+1; // 右半部分的工作指针// 两者较小的赋值给tmp数组while (p1 <= mid && p2 <= R) {tmp[i++] = (vec[p1] <= vec[p2] ? vec[p1++] : vec[p2++]); }// 收尾while (p1 <= mid) {tmp[i++] = vec[p1++];}while (p2 <= R) {tmp[i++] = vec[p2++];}// 赋值for (int i = 0; i < n; ++i) {vec[L+i] = tmp[i];  // key:注意递归中赋值的起始位置}}
// 递归形式
void Process(vector<int> &vec, int L, int R) {// 递归出口if (L == R) return ;// 划分int mid = L + ((R-L)>>1);Process(vec, L, mid);Process(vec, mid+1, R);// 合并Merge(vec, L, mid, R);
}
// 非递归形式
void Process(vector<int> &vec) {if (vec.size() < 2) return ;const int n = vec.size();int merge_size = 1;		// 每次合并单位while (merge_size < N) {int L = 0; 		// 每次从0开始while (L < N) {	// 合并相邻merge_size的区间int mid = L+merge_size-1;if (mid >= N) break;	// 避免右边界溢出int R = min(mid+merge_size(), N-1);merge(vec, L, mid, R);L = R+1;}if (merge_size > N / 2) break;	// 避免溢出,提前停止merge_size <<= 1;}
}
  1. 求数组小和,表示第i个数左侧小于等于该数的个数,然后整个数组的每个数的小和相加
    • 逆反:相当于求第i个数右侧比i值大的个数
    • 归并排序可以解决两个范围比较的问题
// 将两个数组从小到大合并成为一个
int Merge(vector<int> &vec, int L, int mid, int R) {const int n = R-L+1;vector<int> tmp(n, 0);  // 注意长度int i = 0;      // 工作指针int p1 = L;     // 左半部分的工作指针int p2 = mid+1; // 右半部分的工作指针// 两者较小的赋值给tmp数组int res = 0;while (p1 <= mid && p2 <= R) {// 在右组中找到比左组大的数,右组是有序的,所以可以直接通过下标计算出右组更大的有几个res += vec[p1] < vec[p2] ? (R-p2+1)*vec[p1] : 0;tmp[i++] = (vec[p1] < vec[p2] ? vec[p1++] : vec[p2++]); }// 收尾while (p1 <= mid) {tmp[i++] = vec[p1++];}while (p2 <= R) {tmp[i++] = vec[p2++];}// 赋值for (int i = 0; i < n; ++i) {vec[L+i] = tmp[i];  // key:注意递归中赋值的起始位置}return res;}int Process(vector<int> &vec, int L, int R) {// 递归出口if (L == R) return 0;// 划分int mid = L + ((R-L)>>1);return Process(vec, L, mid) + Process(vec, mid+1, R);+ Merge(vec, L, mid, R);
}

快速排序

  1. partition过程:进行划分但不严格要求两部分内部有序,将小于等于num的数放在左边,将大于等于num的数放在右边
  2. 代码
// 划分
int parititon(vector<int> &vec, int left, int right) {// 随机化处理:避免完全有序的情况int idx = left + rand() % (right - left + 1);swap(vec[left], vec[idx]);// 算法部分int pos = left;int pivot = vec[left];while (left < right) {while (vec[right] >= pivot && left < right) right--;while (vec[left] <= pivot && left < right) left++;swap(vec[left], vec[right]);}swap(vec[left], vec[pos]);return left;
}void QuickSort(vector<int> &vec, int left, int right) {if (left > right) return ;int mid = parititon(vec, left, right);QuickSort(vec, left, mid-1);QuickSort(vec, mid+1, right);}
// main中需要 srand((int)time(NULL));


少年,我观你骨骼清奇,颖悟绝伦,必成人中龙凤。
不如点赞·收藏·关注一波

🚩点此跳转到首行↩︎

参考博客

  1. 对数器
  2. 单调队列
  3. 快速链表quicklist
  4. 《深入理解计算机系统》
  5. 侯捷C++全系列视频
  6. 待定引用
  7. 待定引用
  8. 待定引用

http://www.ppmy.cn/news/1209178.html

相关文章

刷题笔记day15-二叉树层序遍历

层序遍历 /*** Definition for a binary tree node.* type TreeNode struct {* Val int* Left *TreeNode* Right *TreeNode* }*/import ("container/list" )func levelOrder(root *TreeNode) [][]int {// 思路1&#xff1a;此处肯定要使用队列result : …

数据库数据恢复—MSSQL报错“附加数据库错误823”如何恢复数据?

数据库故障&分析&#xff1a; MSSQL Server数据库比较常见的报错是“附加数据库错误823”。如果数据库有备份&#xff0c;只需要还原备份即可&#xff1b;如果无备份或者备份不可用&#xff0c;则需要使用专业的数据恢复手段去恢复数据。 MSSQL Server数据库出现“823”的报…

3.0.3版vsftpd所支持的FTP命令

2023年11月9日&#xff0c;周四下午 ABOR&#xff1a;中止当前的数据连接。ACCT&#xff1a;提供用户帐户信息&#xff0c;通常用于特定的站点访问控制。ALLO&#xff1a;为服务器上的文件分配存储空间。APPE&#xff1a;将数据添加到现有的远程文件中。CDUP&#xff1a;将当前…

JS 处理文档选择和范围创建【createRange | getSelection】

介绍 1、const selection window.getSelection(); 说明&#xff1a; 1、用于获取用户当前文档选择的对象&#xff1b; 2、它返回一个 Selection 对象&#xff0c;该对象代表了用户选择的文本范围&#xff08;可以包含一个或多个范围&#xff0c;因为用户可以同时选择多个不相…

Flutter笔记:聊一聊依赖注入(上)

Flutter笔记 聊一聊依赖注入&#xff08;上&#xff09; 作者&#xff1a;李俊才 &#xff08;jcLee95&#xff09;&#xff1a;https://blog.csdn.net/qq_28550263 邮箱 &#xff1a;291148484163.com 本文地址&#xff1a;https://blog.csdn.net/qq_28550263/article/details…

NIO 笔记(一)基础内容

【笔记来自&#xff1a;it白马】 NIO基础 **注意&#xff1a;**推荐完成JavaSE篇、JavaWeb篇的学习再开启这一部分的学习&#xff0c;如果在这之前完成了JVM篇&#xff0c;那么看起来就会比较轻松了。 在JavaSE的学习中&#xff0c;我们了解了如何使用IO进行数据传输&#xf…

绕过防盗链的几种方式

需要进行防盗链的绕过&#xff0c;我们必须先要了解Iframe、Referer和XMLHttpRequest对象的基本知识 目录 Iframe 基本用法 sandbox 属性 loading 属性 Referer Referrer-policy 设置referrer的两种方法 下面举三个将referrer设置为no-referrer的例子&#xff1a; 首先…

【从0到1设计一个网关】性能优化---缓存

文章目录 为什么要用缓存?Caffeine Cache使用Caffeine效果演示为什么要用缓存? 首先先了解一下为什么在网关中我们需要用到缓存。 我们可以从如下几点来入手这个问题: 处理大规模流量: 网关是系统的入口,需要处理大规模的请求流量。高性能的网关能够快速而有效地处理大量…