当前位置:网站首页>颜色分类Ⅱ

颜色分类Ⅱ

2022-06-13 12:35:00 影中人lx

题目
在这里插入图片描述
方法一:分治法

算法思路:
每次选定一个中间的颜色,这个中间的颜色用给出的k来决定,将小于等于中间的颜色的就放到左边,大于中间颜色的就放到右边,然后分别再递归左右两半。
代码思路:
递归函数设置四个参数,序列需要处理区间的左右端点和处理的颜色区间
根据给定的颜色区间决定中间的颜色
将小于等于中间的颜色的就放到左边,大于中间颜色的就放到右边
递归左右两半,直到颜色区间长度等于1

class Solution {
    
public:
    //分治法
    void sortColors2(vector<int> &colors, int k) {
    
    //如果colors数组为空或者只有1个数
    //直接返回原数组
        if(colors.size()<2){
    
            return ;
        }
        mysort1(colors,0,colors.size()-1,1,k);
    }
    //start和end分别是排序范围的开始和结束,colorstart,colorend分别是需要排序颜色的大小
    void mysort1(vector<int>&colors,int start,int end,int colorstart,int colorend){
    
        int left=start,right=end;
        if(left>=right||colorstart==colorend){
    
            return ;
        }
        //把小于colorkey的放在左边,大于colorkey的放在右边
        int colorkey=(colorend-colorstart)/2+colorstart;
        while(left<=right){
    
        //在左边区间找到一个大于colorkey的数
            while(left<=right&&colors[left]<=colorkey){
    
                left++;
            }
        //在右边区间找到一个小于colorkey的数
            while(left<=right&&colors[right]>colorkey){
    
                right--;
            }
            if(left<=right){
    
                swap(colors[left],colors[right]);
            }
        }
        //对左区间和右区间分别进行递归
        mysort1(colors,start,right,colorstart,colorkey);
        mysort1(colors,left,end,colorkey+1,colorend);
    }
};

方法二:在原数组进行的计数排序

算法思路
我们用负数代表数字出现的次数,例如colors[i]=-cnt表示数字i出现了cnt次
代码思路
我们从左往右遍历colors数组

  • 若colors[i] > 0且colors[colors[i]] < 0,那么colors[colors[i]] -= 1
  • 若colors[i] > 0且colors[colors[i]] > 0,那么先用临时变量temp存下colors[i],将colors[colors[i]]赋值给colors[i],再将colors[temp] = -1
  • 若colors[i] < 0,跳过
    倒着输出每种颜色
    另外注意数组下标是从0开始,为了避免n==k导致数组越界的情况,colors[i]对应的计数位为colors[colors[i] - 1]
class Solution {
    
public:
    //基于原数组的计数排序法
    void sortColors2(vector<int> &colors, int k) {
    
        if(colors.size()<2){
    
            return ;
        }
        mysort2(colors,k);
    }
    void mysort2(vector<int>&colors,int k){
    
        int index=0;
        while(index<colors.size()){
    
            //如果index已经是计数位,就直接跳过
            if(colors[index]<=0){
    
                index++;
            }
            //如果index不是计数位
            else{
    
                //因为数组的下标是0开始的,所以映射需要减1
                //比如数值为1的个数存放在colors[0]的位置
                //数值为2的个数存放在colors[1]的位置
                int tmp=colors[index]-1;
                //如果colors[tmp]是计数位
                if(colors[tmp]<=0){
    
                    colors[tmp]--;
                    //因为colors[index]被计数了,所以index这个位置被置为0
                    colors[index]=0;
                    index++;
                }
                //如果两个都不是计数位
                //由于是对index进行计数,所以需要保存colors[tmp]的数值
                //然后把colors[index]位置作为是计数位
                else{
    
                    swap(colors[tmp],colors[index]);
                    colors[tmp]=-1;
                }
            }
        }
        //倒着打印数组
        int num=colors.size()-1;
        //值为k的个数存放在数组下标为k-1的位置
        while(k>0){
    
            for(int j=0;j>colors[k-1];j--){
    
                colors[num--]=k;
            }
            k--;
        }
    }
};
原网站

版权声明
本文为[影中人lx]所创,转载请带上原文链接,感谢
https://blog.csdn.net/qq_53893431/article/details/125240219