题目描述

原题链接
给定一个包含红色、白色和蓝色、共 n 个元素的数组 nums ,原地对它们进行排序,使得相同颜色的元素相邻,并按照红色、白色、蓝色顺序排列。
我们使用整数 0、 1 和 2 分别表示红色、白色和蓝色。
必须在不使用库的sort函数的情况下解决这个问题。

示例 1:
输入:nums = [2,0,2,1,1,0]
输出:[0,0,1,1,2,2]

示例 2:
输入:nums = [2,0,1]
输出:[0,1,2]

提示:

  • n == nums.length
  • 1 <= n <= 300
  • nums[i] 为 0、1 或 2

进阶:

  • 你可以不使用代码库中的排序函数来解决这道题吗?
  • 你能想出一个仅使用常数空间的一趟扫描算法吗?

    个人解法

Javascript

排序

这里用快排来展示

  1. /*
  2. * @lc app=leetcode.cn id=75 lang=javascript
  3. *
  4. * [75] 颜色分类
  5. */
  6. // @lc code=start
  7. function swap(arr, a, b) {
  8. var temp = arr[a];
  9. arr[a] = arr[b];
  10. arr[b] = temp;
  11. }
  12. function quickSort(arr, begin, end) {
  13. if (begin >= end - 1) return;
  14. var left = begin;
  15. var right = end;
  16. do {
  17. do left++; while (left < right && arr[left] < arr[begin]);
  18. do right--; while (right > left && arr[right] > arr[begin]);
  19. if (left < right) swap(arr, left, right)
  20. } while (left < right);
  21. var swapPoint = left == right ? right - 1 : right;
  22. swap(arr, begin, swapPoint);
  23. quickSort(arr, begin, swapPoint);
  24. quickSort(arr, swapPoint + 1, end);
  25. }
  26. /**
  27. * @param {number[]} nums
  28. * @return {void} Do not return anything, modify nums in-place instead.
  29. */
  30. var sortColors = function (nums) {
  31. quickSort(nums, 0, nums.length);
  32. };
  33. // @lc code=end

单指针

思路:两次扫描,第一次将所有的0交换道最前面
第二次将所有的1交换到前面
之后2就都在最后面了

  1. /*
  2. * @lc app=leetcode.cn id=75 lang=javascript
  3. *
  4. * [75] 颜色分类
  5. */
  6. // @lc code=start
  7. /**
  8. * @param {number[]} nums
  9. * @return {void} Do not return anything, modify nums in-place instead.
  10. */
  11. var sortColors = function (nums) {
  12. const len = nums.length;
  13. let ptr = 0;
  14. for (let i = 0; i < len; i++) {
  15. if (nums[i] === 0) {
  16. [nums[i], nums[ptr]] = [nums[ptr], nums[i]]; // 交换
  17. ptr++;
  18. }
  19. }
  20. for (let i = ptr; i < len; i++) {
  21. if (nums[i] === 1) {
  22. [nums[i], nums[ptr]] = [nums[ptr], nums[i]];
  23. ptr++;
  24. }
  25. }
  26. };
  27. // @lc code=end

双指针

在单指针的基础上改进,用第一个指针表示0,第二个指针表示1,这样就能一次扫描完成

  1. /*
  2. * @lc app=leetcode.cn id=75 lang=javascript
  3. *
  4. * [75] 颜色分类
  5. */
  6. // @lc code=start
  7. /**
  8. * @param {number[]} nums
  9. * @return {void} Do not return anything, modify nums in-place instead.
  10. */
  11. var sortColors = function (nums) {
  12. const len = nums.length;
  13. let ptr1 = 0;
  14. let ptr2 = 0;
  15. for (let i = 0; i < len; i++) {
  16. if (nums[i] === 0) {
  17. [nums[i], nums[ptr1]] = [nums[ptr1], nums[i]];
  18. if (ptr1 < ptr2) {
  19. [nums[i], nums[ptr2]] = [nums[ptr2], nums[i]];
  20. }
  21. ptr1++;
  22. ptr2++;
  23. } else if (nums[i] === 1) {
  24. [nums[i], nums[ptr2]] = [nums[ptr2], nums[i]];
  25. ptr2++;
  26. }
  27. }
  28. };
  29. // @lc code=end

Java

其他解法

Java

Javascript


双指针2

上面的双指针方法还可以用另一种思路来解决
第一个指针表示0
第二个指针从后面开始,表示2
这样0 移动到最前面,2移动到最后面,这样1就肯定是在中间的了