75. 颜色分类

难度中等

给定一个包含红色、白色和蓝色,一共 n 个元素的数组,**原地**对它们进行排序,使得相同颜色的元素相邻,并按照红色、白色、蓝色顺序排列。

此题中,我们使用整数 0、 1 和 2 分别表示红色、白色和蓝色。

注意:
不能使用代码库中的排序函数来解决这道题。

示例:

输入: [2,0,2,1,1,0]
输出: [0,0,1,1,2,2]

进阶:

分析

循环不变量是这样定义的:

  • 所有在子区间 [0, zero) 的元素都等于 0
  • 所有在子区间 [zero, i) 的元素都等于 1
  • 所有在子区间 [two, len - 1] 的元素都等于 2

说明:设计循环不变量的原则是“不重不漏”。

1、len 是数组的长度;
2、变量 zero 是前两个子区间的分界点,一个是闭区间,另一个就必须是开区间;
3、变量 i 是循环变量,一般设置为开区间,表示 i 之前的元素是遍历过的;
4、two 是另一个分界线,我设计成闭区间。

于是编码要解决以下三个问题:

变量初始化应该如何定义。
在遍历的时候,是先加减还是先交换。
什么时候循环终止。

处理这三个问题,完全看循环不变量的定义

  • 编码的时候,zerotwo 初始化的值就应该保证上面的三个子区间全为空。
  • 在遍历的过程中,“索引先加减再交换”、还是“先交换再加减”就看初始化的时候变量在哪里。
  • 退出循环的条件也看上面定义的循环不变量,在 i == two 成立的时候,上面的三个子区间就正好“不重不漏”地覆盖了整个数组,并且给出的性质成立,题目的任务也就完成了。

以下给出不同的写法,循环不变量的定义写在了注释中。使用“循环不变量”编码是为了便于我们处理细节,也方便别人看懂你的算法。

参考代码 1

import java.util.Arrays;public class Solution {public void sortColors(int[] nums) {int len = nums.length;if (len < 2) {return;}// all in [0, zero) = 0// all in [zero, i) = 1// all in [two, len - 1] = 2// 循环终止条件是 i == two,那么循环可以继续的条件是 i < two// 为了保证初始化的时候 [0, zero) 为空,设置 zero = 0,// 所以下面遍历到 0 的时候,先交换,再加int zero = 0;// 为了保证初始化的时候 [two, len - 1] 为空,设置 two = len// 所以下面遍历到 2 的时候,先减,再交换int two = len;int i = 0;// 当 i == two 上面的三个子区间正好覆盖了全部数组// 因此,循环可以继续的条件是 i < twowhile (i < two) {if (nums[i] == 0) {swap(nums, i, zero);zero++;i++;} else if (nums[i] == 1) {i++;} else {two--;swap(nums, i, two);}}}private void swap(int[] nums, int index1, int index2) {int temp = nums[index1];nums[index1] = nums[index2];nums[index2] = temp;}
}

参考代码 2

public class Solution {public void sortColors(int[] nums) {int len = nums.length;if (len < 2) {return;}// all in [0, zero] = 0// all in (zero, i) = 1// all in (two, len - 1] = 2// 为了保证初始化的时候 [0, zero] 为空,设置 zero = -1,// 所以下面遍历到 0 的时候,先加,再交换int zero = -1;// 为了保证初始化的时候 (two, len - 1] 为空,设置 two = len - 1// 所以下面遍历到 2 的时候,先交换,再减int two = len - 1;int i = 0;// 当 i == two 的时候,还有一个元素还没有看,// 因此,循环可以继续的条件是 i <= twowhile (i <= two) {if (nums[i] == 0) {zero++;swap(nums, i, zero);i++;} else if (nums[i] == 1) {i++;} else {swap(nums, i, two);two--;}}}private void swap(int[] nums, int index1, int index2) {int temp = nums[index1];nums[index1] = nums[index2];nums[index2] = temp;}
}

说明:这种做法是我在 Java 的 JDK 的源码中 Arrays.sort() 中学到的。

我的体会是:

  • 编码者应该在代码中使用注释表达这段代码编写的算法思想,提醒自己也方便他人。
  • 但是源代码中类似 ++k <= greata[++left] >= a[left - 1] 这样的代码建议不要写,会给阅读者带来理解上的障碍,这种做法也是《阿里巴巴 Java 开发手册》中不推荐的,理由是:变量的值发生变化是一个很重要的逻辑,应该单独成为一行,否则不利于调试和以后定位问题,这种语法糖我个人认为应该禁止使用。

【leetcode】75.颜色分类(多种解法,超详细图文解析)相关推荐

  1. LeetCode - 75 颜色分类

    给定一个包含红色.白色和蓝色.共 n 个元素的数组 nums ,原地对它们进行排序,使得相同颜色的元素相邻,并按照红色.白色.蓝色顺序排列.我们使用整数 0. 1 和 2 分别表示红色.白色和蓝色. ...

  2. leetcode —— 75. 颜色分类

    给定一个包含红色.白色和蓝色,一共 n 个元素的数组,原地对它们进行排序,使得相同颜色的元素相邻,并按照红色.白色.蓝色顺序排列. 此题中,我们使用整数 0. 1 和 2 分别表示红色.白色和蓝色. ...

  3. LeetCode 75. 颜色分类(Sort Colors)

    题目描述 给定一个包含红色.白色和蓝色,一共 n 个元素的数组,原地对它们进行排序,使得相同颜色的元素相邻,并按照红色.白色.蓝色顺序排列. 此题中,我们使用整数 0. 1 和 2 分别表示红色.白色 ...

  4. Leetcode 75. 颜色分类 (每日一题 20210817)

    给定一个包含红色.白色和蓝色,一共 n 个元素的数组,原地对它们进行排序,使得相同颜色的元素相邻,并按照红色.白色.蓝色顺序排列.此题中,我们使用整数 0. 1 和 2 分别表示红色.白色和蓝色.示例 ...

  5. leetcode 75. 颜色分类(双指针)

    给定一个包含红色.白色和蓝色,一共 n 个元素的数组,原地对它们进行排序,使得相同颜色的元素相邻,并按照红色.白色.蓝色顺序排列. 此题中,我们使用整数 0. 1 和 2 分别表示红色.白色和蓝色. ...

  6. LeetCode 75 颜色分类

    题目描述 给定一个包含红色.白色和蓝色,一共 n 个元素的数组,原地对它们进行排序,使得相同颜色 的元素相邻,并按照红色.白色.蓝色顺序排列.此题中,我们使用整数 0. 1 和 2 分别表示红色.白色 ...

  7. 电路中滤波电容和退耦电容_超详细图文解析,电容器在电路中的27种作用

    1.滤波电容 滤波电容接在直流电压的正负极之间,以滤除直流电源中不需要的交流成分,使直流电平滑,通常采用大容量的电解电容,也可以在电路中同时并接其它类型的小容量电容以滤除高频交流电. 2.退耦电容 退 ...

  8. Leetcode算法Java全解答--75. 颜色分类

    Leetcode算法Java全解答–75. 颜色分类 文章目录 Leetcode算法Java全解答--75. 颜色分类 题目 想法 结果 总结 代码 我的答案 大佬们的答案 测试用例 其他 题目 给定 ...

  9. 75. 颜色分类(C++实现)

    文章目录 题目 思路--三指针 题目 题目链接:75. 颜色分类) 思路–三指针 其实颜色分类就是对 0 1 2 这三个数字进行排序,但是排序都是有效率之分的,我们希望可以通过一种高效的方法去排序这三 ...

最新文章

  1. python哪一版好用-Python最好用的编辑器是哪款?北京老男孩教育
  2. 纵表、横表互转的SQL
  3. Spring boot (1)--- 第一个应用程序helloworld
  4. python 赋值、浅拷贝、深拷贝学习实践
  5. 深度学习:NLP之词嵌入(Word Embedding)
  6. 服务器虚拟计算节点,什么是云服务器计算节点
  7. Springboot整合mqtt客户端,实现客户端之间的交互(mqtt服务器为apollo1.7)【windows下]】
  8. vijos1655萌萌的糖果博弈
  9. Juicer – 一个 JavaScript 模板引擎的实现和优化
  10. linux office转换pdf
  11. 我在CSDN参与的3000个帖子
  12. 【转】如何实现小型WEB搜索引擎(C# SQL Server全文检索 Asp.net)
  13. 转《MCU低功耗设计》
  14. 设想无人值守的自动化测试方案
  15. 第七届科技节获奖及建模论文相似度名单公示
  16. 6、网络设计时原来还要遵循这些原则。
  17. 常用数据库的基因ID
  18. libc and libc++
  19. 微习惯瘦身,一天一个俯卧撑就够了吗?
  20. java ee 中文_javaee中的中文乱码处理

热门文章

  1. hibernate的查询条件lt_hibernate的多条件查询——Criteria Query的应用
  2. 【矩阵论】内积空间与等距变换(2)
  3. Python后端开发要求
  4. 深信服AC苹果用户上网认证失败,认证mac地址和用户终端mac地址不一致
  5. 静态网页爬虫教程(3)文本的提取和保存
  6. JAVA醋坊定制销售平台计算机毕业设计Mybatis+系统+数据库+调试部署
  7. python sequence_干货来袭!Python高阶函数使用总结~
  8. OpenCV边缘检测
  9. Gate Level Simulation (前仿及后仿总结)
  10. Python爬虫笔记——Url解码时,如何将汉字转化为以 %开头的 gb2312 编码 和 将以%号开头的编码转化为汉字 的示例