算法—分治

        

        分而治之:指的是当主问题可以被分解为一个相同次级问题加相同基本问题时,采用这种思想,基本问题指问题规模最小时的情况,次级问题是指主问题的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 ;
    }
};

  • 5
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值