当前位置: 首页 > news >正文

二分、快排、堆排与双指针

二分

int Binary_Search(vector<int> A,int key){int n=A.size();int low=0,high=n-1,mid;while(low<=high){mid=(low+high)/2;if(A[mid]==key)return mid;else if(A[mid]>key)high=mid-1;elselow=mid+1;	}return -1;
}

折半插入排序

——找到第一个 ≥ \ge tem的元素

void InsertSort(vector<int> A){int n=A.size();int low,high,mid;for(int i=1;i<=n;i++){int tem=A[i];low=1;high=i-1;while(low<=high){mid=(low+high)/2;if(A[mid]>tem)	//只要A[high]>tem,就不断往后移high=mid-1;	else	//先往右移,后续往做移low=mid+1;}for(int j=i-1;j>=high+1;j--)A[j+1]=A[j];A[high+1]=tem;}

在非递减数组中找到比x小的最后一个元素和比x大的第一个元素

  • 每次有要处理的就if-else
  • 为了避免无限循环>>[begin,mid-1] U mid U [mid+1,end]
  • 为了产生mid+1对nums[mid+1]进行讨论
class Solution {
public:int search_left(vector<int> nums,int begin,int end,int target){if(begin>end)   return -1;if(nums[end]<target)return end;if(nums[begin]>=target)return begin-1;else {int mid=(begin+end)/2;if(nums[mid]>=target)return search_left(nums,begin,mid-1,target);else {if(mid==nums.size()-1)return -1;else if(nums[mid+1]>=target)return mid;else  return search_left(nums,mid+1,end,target);}}}int search_right(vector<int> nums,int begin,int end,int target){if(begin>end)   return nums.size();if(nums[begin]>target){return begin;}  if(nums[end]<=target){return end+1;}else {int mid=(begin+end)/2;if(nums[mid]<=target)return search_right(nums,mid+1,end,target);else{if(mid==0)  return nums.size();if(nums[mid-1]<=target) return mid;else    return search_right(nums,begin,mid-1,target);}}}vector<int> searchRange(vector<int>& nums, int target) {int N=nums.size();int left=search_left(nums,0,N-1,target);int right=search_right(nums,0,N-1,target);vector<int> ans(2);if(left>=right-1){ans[0]=-1;  ans[1]=-1;}else {ans[0]=left+1;···ans[1]=right-1;}        return ans; }
};

三数之和

  1. 三数之和首先把nums[0]~nums[n-1]排序
  2. 在a固定的情形下,条件: 每次c及其右侧所有可能都被确定,
    利用贪心性质:if b+c+a<0, b左侧的在c往左移的过程中更不可能,因此b++
    else if b+c+a>0,c及其右侧在b右移的过程中更不可能,因此c–,
    b+c+a=0,当前的b及其左侧已不可能,不妨b++,
class Solution {
public:vector<vector<int>> threeSum(vector<int>& nums) {int n = nums.size();sort(nums.begin(), nums.end());vector<vector<int>> ans;// 枚举 afor (int first = 0; first < n; ++first) {// 需要和上一次枚举的数不相同if (first > 0 && nums[first] == nums[first - 1]) {continue;}// c 对应的指针初始指向数组的最右端int third = n - 1;int target = -nums[first];// 枚举 bfor (int second = first + 1; second < n; ++second) {// 需要和上一次枚举的数不相同if (second > first + 1 && nums[second] == nums[second - 1]) {continue;}// 需要保证 b 的指针在 c 的指针的左侧while (second < third && nums[second] + nums[third] > target) {--third;}// 如果指针重合,随着 b 后续的增加// 就不会有满足 a+b+c=0 并且 b<c 的 c 了,可以退出循环if (second == third) {break;}if (nums[second] + nums[third] == target) {ans.push_back({nums[first], nums[second], nums[third]});}}}return ans;}
};`

四数相加

  • 要返回解,只能2层循环+双指针,2个数组的双指针,不能输出全部解
class Solution {
public:int fourSumCount(vector<int>& nums1, vector<int>& nums2, vector<int>& nums3, vector<int>& nums4) {unordered_map<int,int>hash;int res = 0;int n =nums1.size();for(int i=0;i<n;i++){for(int j=0;j<n;j++){hash[nums1[i]+nums2[j]]++;}} for(int i=0;i<n;i++){for(int j=0;j<n;j++){auto it = hash.find(-(nums3[i]+nums4[j]));if(it!=hash.end()){res += it->second;}}}return res;}
};

滑动窗口最大值

mean1: priority_queue

class Solution {
public:vector<int> maxSlidingWindow(vector<int>& nums, int k) {auto cmp = [](const pair<int, int>& a, const pair<int, int>& b) -> bool { return a.first < b.first; };priority_queue<pair<int, int>, vector<pair<int, int>>, decltype(cmp)> pq(cmp);int n=nums.size();vector<int> ans;for(int i=0;i<n;i++){pq.push({nums[i],i});while(pq.top().second<i-k+1){pq.pop();}if(i>=k-1)ans.push_back(pq.top().first);}return ans;}
};

mean2: 单调队列

deque=双端队列,有clear()

class Solution {
public:vector<int> maxSlidingWindow(vector<int>& nums, int k) {int n = nums.size();deque<int> q;for (int i = 0; i < k; ++i) {while (!q.empty() && nums[i] >= nums[q.back()]) {q.pop_back();}q.push_back(i);}vector<int> ans = {nums[q.front()]};for (int i = k; i < n; ++i) {while (!q.empty() && nums[i] >= nums[q.back()]) {q.pop_back();}q.push_back(i);while (q.front() <= i - k) {q.pop_front();}ans.push_back(nums[q.front()]);}return ans;}
};

Exp++

  1. 本质是用堆化简排序

双指针

for (int i = 0, j = 0; i < n; i ++ )  // j从某一位置开始,不一定是0
{while (j < i && check(i, j)) j ++ ;// 具体问题的逻辑
}
常见问题分类:(1) 对于一个序列,用两个指针维护一段区间,比如快排的划分过程(2) 对于两个序列,维护某种次序,比如归并排序中合并两个有序序列的操作
  1. 双指针算法的核心思想(作用):优化.
  2. 在利用双指针算法解题时,考虑原问题如何用暴力算法解出,观察是否可构成单调性,若可以,就可采用双指针算法对暴力算法进行优化.
  3. 当我们采用朴素的方法即暴力枚举每一种可能的情况,时间复杂度为O(n*n),双指针降为O(n).
http://www.lryc.cn/news/301193.html

相关文章:

  • 微信小程序步数返还的时间戳为什么返回的全是1970?
  • Python函数——函数介绍
  • 【Linux系统化学习】文件重定向
  • 防火墙工作模式详解
  • CCF编程能力等级认证GESP—C++6级—20231209
  • ES6 ~ ES11 学习笔记
  • 001 - Hugo, 创建一个网站
  • 前端开发:Vue框架与前端部署
  • 【leetcode】深搜、暴搜、回溯、剪枝(C++)3
  • 社区养老|社区养老服务系统|基于springboot社区养老服务系统设计与实现(源码+数据库+文档)
  • 云计算基础-存储虚拟化(深信服aSAN分布式存储)
  • 数学实验第三版(主编:李继成 赵小艳)课后练习答案(十二)(3)
  • CSS Transition:为网页元素增添优雅过渡效果
  • JDK 17 新特性 (一)
  • 杨中科 ASP.NET DI综合案例
  • 蓝桥杯嵌入式第12届真题(完成) STM32G431
  • C#系列-多线程(4)
  • VS如何调试C运行时库
  • 软件工程师,超过35岁怎么办
  • 通过 Prometheus 编写 TiDB 巡检脚本(脚本已开源,内附链接)
  • sql语句学习(一)--查询
  • 【HTML】交友软件上照片的遮罩是如何做的
  • 【Java EE初阶十二】网络编程TCP/IP协议(一)
  • element-ui解决上传文件时需要携带请求数据的问题
  • 【AI视野·今日NLP 自然语言处理论文速览 第七十九期】Thu, 18 Jan 2024
  • Docker容器运行
  • 【计算机网络】网络层之IP协议
  • 2024/2/17 图论 最短路入门 dijkstra 1
  • 交通管理|交通管理在线服务系统|基于Springboot的交通管理系统设计与实现(源码+数据库+文档)
  • 最适合初学者的Python入门详细攻略,一文讲清,赶紧收藏!