力扣 颜色分类

双指针,滑动窗口,排序。

题目

简单做法,单指针,一直遍历,先排小再排大。找到是0的与指针指的位置做交换,交换后指针在这个位置的任务就结束了,接着去定住下一个,然后依次遍历完一趟后找到所有的0,接着下一个数,从这个指针的位置开始一直在后面,找到所有的1做交换,依次重复,然后剩下的就是2了。

时间复杂度: O(n),空间复杂度: O(1)。

java 复制代码
class Solution {
    public void sortColors(int[] nums) {
        int n = nums.length;
        int p0 = 0, p1 = 0;
        for (int i = 0; i < n; ++i) {
            if (nums[i] == 1) {
                int temp = nums[i];
                nums[i] = nums[p1];
                nums[p1] = temp;
                ++p1;
            } else if (nums[i] == 0) {
                int temp = nums[i];
                nums[i] = nums[p0];
                nums[p0] = temp;
                if (p0 < p1) {
                    temp = nums[i];
                    nums[i] = nums[p1];
                    nums[p1] = temp;
                }
                ++p0;
                ++p1;
            }
        }
    }
}

也可以用hashmap去存每个颜色对应的次数,接着用一个指针去进行填充数组。

时间复杂度: O(n),空间复杂度: O(1)。

java 复制代码
class Solution {
    public void sortColors(int[] nums) {
    // 创建一个 HashMap 来存储每个颜色(数字)的频率
    HashMap<Integer, Integer> map = new HashMap<>();

    // 遍历数组 nums,将每个颜色出现的频次记录到 HashMap 中
    for (int i = 0; i < nums.length; i++) {
        map.put(nums[i], map.getOrDefault(nums[i], 0) + 1);
    }

    // 使用指针来填充数组
    int index = 0;
    
    // 按照颜色的顺序填充数组
    for (int color = 0; color <= 2; color++) {
        int count = map.getOrDefault(color, 0);  // 获取当前颜色的出现次数
        for (int i = 0; i < count; i++) {
            nums[index++] = color;  // 从当前位置填充当前颜色
        }
    }
}
}

以上都是遍历了两趟,那使用一趟时就得用双指针或三指针了。用一个指针从头扫到尾端做一趟遍历,找到对应的数与左右指针交换,找到一的时候,则直接将遍历的指针移动。用一个指针记录低的数,完成任务后右移,用一个指针记录高的数,完成任务后左移。用这个遍历的指针依次交换就可以排好序了。

时间复杂度: O(n),空间复杂度: O(1)。

java 复制代码
class Solution {
    public void sortColors(int[] nums) {
        int low = 0, mid = 0, high = nums.length - 1;
        
        while (mid <= high) {
            if (nums[mid] == 0) {
                // 当前数字是0,交换 low 和 mid
                swap(nums, low++, mid++);
            } else if (nums[mid] == 1) {
                // 当前数字是1,继续往后移
                mid++;
            } else {
                // 当前数字是2,交换 mid 和 high
                swap(nums, mid, high--);
            }
        }
    }

    private void swap(int[] nums, int i, int j) {
        int temp = nums[i];
        nums[i] = nums[j];
        nums[j] = temp;
    }
}
java 复制代码
class Solution {
    public void sortColors(int[] nums) {
        int n = nums.length;
        int p0 = 0, p2 = n - 1;
        for (int i = 0; i <= p2; ++i) {
            while (i <= p2 && nums[i] == 2) {
               swap(nums,i,p2--);
            }
            if (nums[i] == 0) {
                swap(nums,i,p0++);
            }
        }
    }
    private void swap(int[] nums,int i,int j){
         int tmp=nums[i];
         nums[i]=nums[j];
         nums[j]=tmp;

    }
}

本题对准指针做交换可得到较好的排序,然后也要看一下交换后的情况是不是还需再排。

相关推荐
eternal__day15 分钟前
Spring Cloud 多机部署与负载均衡实战详解
java·spring boot·后端·spring cloud·负载均衡
颜淡慕潇19 分钟前
Redis 实现分布式锁:深入剖析与最佳实践(含Java实现)
java·redis·分布式
程序员秘密基地25 分钟前
基于vscode,idea,java,html,css,vue,echart,maven,springboot,mysql数据库,在线考试系统
java·vue.js·spring boot·spring·web app
何中应26 分钟前
【设计模式-5】设计模式的总结
java·后端·设计模式
草莓熊Lotso27 分钟前
【数据结构初阶】--算法复杂度的深度解析
c语言·开发语言·数据结构·经验分享·笔记·其他·算法
KyollBM33 分钟前
【CF】Day75——CF (Div. 2) B (数学 + 贪心) + CF 882 (Div. 2) C (01Trie | 区间最大异或和)
c语言·c++·算法
吾日三省吾码44 分钟前
Spring 团队详解:AOT 缓存实践、JSpecify 空指针安全与支持策略升级
java·spring·缓存
CV点灯大师1 小时前
C++算法训练营 Day10 栈与队列(1)
c++·redis·算法
风象南1 小时前
SpringBoot的5种日志输出规范策略
java·spring boot·后端
GGBondlctrl1 小时前
【leetcode】递归,回溯思想 + 巧妙解法-解决“N皇后”,以及“解数独”题目
算法·leetcode·n皇后·有效的数独·解数独·映射思想·数学思想