分而治之:指的是当主问题可以被分解为一个相同次级问题加相同基本问题时,采用这种思想,基本问题指问题规模最小时的情况,次级问题是指主问题的n级降低n-1级的问题。
具体实现:多数采用递归操作分解,然后递归操作,需要注意的是函数头,函数体,以及递归出口,函数头:由问题所需变量指定,递归出口由问题最小规模返回决定,函数体看问题具体的需要的信息决定。
75. 颜色分类 - 力扣(LeetCode)
class Solution {
public:void sortColors(vector<int>& nums) {int left=-1;int right=nums.size();int cur=0;while(cur<right){if(nums[cur]==0) swap(nums[++left],nums[cur++]);else if(nums[cur]==2) swap(nums[--right],nums[cur]);else cur++;}return ;}
};
分治-快速排序:下面这三题:都是快排,其中第一题快排,第二题,在快排的基础上,进行剪枝,避免无用的排序,第三题同理,也是避免无用排序。通过设置进入那个递归来实现。
. - 力扣(LeetCode)
class Solution { public:vector<int> sortArray(vector<int>& nums) {srand(time(0));sort1(nums,0,nums.size()-1);return nums;} void sort1(vector<int>& nums,int left,int right){if(left>=right) return;//int key=Getrand(nums,left,right);//swap(nums[left],key);Ⅲ、交换会覆盖一个,不是交换int cur=left;int l=left-1; int r=right+1;while(cur<r){//Ⅱ、cur判断数据时,之后可能会越界,所以一次只能判断一个条件,然后需要判断cur<r,不能多个if。if(nums[cur]>key) swap(nums[cur],nums[--r]);else if(nums[cur]<key) swap(nums[cur++],nums[++l]);else if(nums[cur]==key) cur++;}sort1(nums,left,l);sort1(nums,r,right);}int Getrand(vector<int>& nums,int left,int right){int rd=rand();return nums[rd%(right-left+1)+left]; //Ⅰ:记得+left,否则超范围,} };
215. 数组中的第K个最大元素 - 力扣(LeetCode)
数组中第k个最大元素,①:快速选择,利用快排思想(三路划分),实现O(n),②:利用优先队列(堆):找大的就是用小根堆。找小的用大根堆。O(Nlog2k);
class Solution { public:int findKthLargest(vector<int>& nums, int k) {srand(time(0));return qsort(nums,0,nums.size()-1,k);}int qsort(vector<int>& nums,int l,int r,int k){int key=GetRand(nums,l,r);int cur=l; int left=l-1;int right=r+1;while(cur<right){if(nums[cur]>key) swap(nums[cur++],nums[++left]);else if(nums[cur]<key) swap(nums[cur],nums[--right]);else cur++;}int a=left-l+1; int b=cur-left-1;int c=r-right+1;if(k<=a) return qsort(nums,l,left,k);else if(k>a&&k<=a+b) return key;else return qsort(nums,right,r,k-a-b);}int GetRand(vector<int>& nums,int l,int r){int rd=rand();return nums[rd%(r-l+1)+l];}};
LCR 159. 库存管理 III - 力扣(LeetCode)
class Solution { public:vector<int> inventoryManagement(vector<int>& stock, int cnt) {//如何提取区间srand(time(0));qsort(stock,0,stock.size()-1,cnt);return vector<int>(stock.begin(),stock.begin()+cnt);}void qsort(vector<int>& stock,int l,int r,int cnt){if(l>=r) return ;//若没有则,getrand会出错;%0错误。int key=GetRand(stock,l,r);int cur=l,left=l-1,right=r+1;while(cur<right){if(stock[cur]<key) swap(stock[cur++],stock[++left]);else if(stock[cur]>key) swap(stock[cur],stock[--right]);else cur++;}int a=left-l+1; int b=right-left-1; int c=r-right+1;if(cnt<=a) qsort(stock,l,left,cnt);else if(cnt<=a+b) return ;else qsort(stock,right,r,cnt-a-b);}int GetRand(vector<int>& stock,int l,int r){int rd=rand();return stock[rd%(r-l+1)+l];} };
分治——归并排序
912. 排序数组 - 力扣(LeetCode)
class Solution {vector<int> tmp;
public:vector<int> sortArray(vector<int>& nums) {//归并tmp.resize(nums.size());MageSort(nums,0,nums.size()-1);return nums;}void MageSort(vector<int>& nums,int l,int r){if(l>=r) return;int mid=l+(r-l)/2;MageSort(nums,l,mid);MageSort(nums,mid+1,r);int cur1=l;int cur2=mid+1;int cur=l;while(cur1<=mid&&cur2<=r){if(nums[cur1]<=nums[cur2]){tmp[cur++]=nums[cur1++];}else if(nums[cur1]>nums[cur2]){tmp[cur++]=nums[cur2++];}}while(cur1<=mid) tmp[cur++]=nums[cur1++];while(cur2<=r) tmp[cur++] =nums[cur2++];//拷贝回去int left=l,right=r;while(left<=right) {nums[left]=tmp[left];//*****只有一个left++,首先执行”=“左边的那个部分语句,所有left拷贝给left+1.left++;}return;}
};
LCR 170. 交易逆序对的总数 - 力扣(LeetCode)
class Solution {vector<int> tmp;
public:int reversePairs(vector<int>& record) {int ret=0;tmp.resize(record.size());return magesort(record,0,record.size()-1,ret);}int magesort(vector<int>& record ,int left,int right,int& ret){if(left>=right) return 0;int mid=left+(right-left)/2;magesort(record,left,mid,ret);magesort(record,mid+1,right,ret);int cur=left; int cur1=left,cur2=mid+1;while(cur1<=mid&&cur2<=right){if(record[cur1]<=record[cur2]) tmp[cur++]=record[cur2++];//降序。else{ret+=right-cur2+1;//****记录左边数组的每个值对应的,右边小于它的个数,right-cur2+1是降序tmp[cur++]=record[cur1++];}}while(cur1<=mid) tmp[cur++]=record[cur1++];while(cur2<=right) tmp[cur++]=record[cur2++];//拷贝回去,复原for(int i=left;i<=right;i++){//*****拷贝要left到right。完整一段record[i]=tmp[i];}return ret;}
};
315. 计算右侧小于当前元素的个数 - 力扣(LeetCode)
class Solution {vector<int> tmp;vector<int> tmp_index;vector<int> index;vector<int> ret;
public:vector<int> countSmaller(vector<int>& nums) {ret.resize(nums.size());index.resize(nums.size());for(int i=0;i<nums.size();i++){//建立变换后的下标[i]与原下标i之间的映射index[i]=i;}tmp.resize(nums.size());tmp_index.resize(nums.size());MageSort(nums,0,nums.size()-1);return ret;}void MageSort(vector<int>& nums,int left,int right){if(left>=right) return;int mid=left+(right-left)/2;MageSort(nums,left,mid);MageSort(nums,mid+1,right);int cur=left;int cur1=left; int cur2=mid+1;while(cur1<=mid&&cur2<=right){if(nums[cur2]<nums[cur1]){//降序,求右区间小于cur1的个数ret[index[cur1]]+=right-cur2+1;tmp[cur]=nums[cur1];tmp_index[cur++]=index[cur1++];//**1***保持映射}else{tmp[cur]=nums[cur2];tmp_index[cur++]=index[cur2++];}}while(cur1<=mid) {tmp[cur]=nums[cur1];tmp_index[cur++]=index[cur1++];}while(cur2<=right){tmp[cur]=nums[cur2];//**1**多加了++tmp_index[cur++]=index[cur2++];}//还原for(int i=left;i<=right;i++){nums[i]=tmp[i];index[i]=tmp_index[i];}}};
493. 翻转对 - 力扣(LeetCode)
class Solution {int ret=0;vector<int> tmp;
public:int reversePairs(vector<int>& nums) {int n=nums.size();tmp.resize(n);MageSort(nums,0,n-1);return ret;}void MageSort(vector<int>& nums,int left,int right){if(left>=right) return ;int mid=(left+right)>>1;MageSort(nums,left,mid);MageSort(nums,mid+1,right);int cur1=left; int cur2=mid+1;while(cur1<=mid&&cur2<=right){// cout<<left<<" "<<mid<<" "<<mid+1<<" "<<right<<endl;//**1**打印也会出现超时的错误// cout<<nums[cur1]/2.0<<" "<<nums[cur2]<<endl;if(nums[cur1]/2.0>nums[cur2]){//**2***一定要2.0,否则会出现3/2不大于1的情况,降序ret+=right-cur2+1;cur1++;}else{cur2++;}} int cur=left; cur1=left; cur2=mid+1;while(cur1<=mid&&cur2<=right){if(nums[cur1]>=nums[cur2]){tmp[cur++]=nums[cur1++];}else{;tmp[cur++]=nums[cur2++];}}while(cur1<=mid) tmp[cur++]=nums[cur1++];while(cur2<=right)tmp[cur++]=nums[cur2++];//还原for(int i=left;i<=right;i++){nums[i]=tmp[i];}return ;}
};