题目链接:https://leetcode.com/problems/sort-colors/
题目:
Given an array with n objects colored red, white or blue, sort them so that objects of the same color are adjacent, with the colors in the order red, white and blue.
Here, we will use the integers 0, 1, and 2 to represent the color red, white, and blue respectively.
Note:
You are not suppose to use the library's sort function for this problem.
click to show follow up.
Follow up:
A rather straight forward solution is a two-pass algorithm using counting sort.
First, iterate the array counting number of 0's, 1's, and 2's, then overwrite array with total number of 0's, then 1's and followed by 2's.
Could you come up with an one-pass algorithm using only constant space?
解题思路:
最初想到的是,统计每一个数字出现的个数(HashMap),然后再在数组中根据数字的个数来填充它们。
经过题目下的提示,且要排序的数字范围在 0~100 ,考虑计数排序。
计数排序算法的步骤如下:
1. 找出待排序的数组中最大和最小的元素
2. 统计数组中每个值为i的元素出现的次数,存入数组C的第i项
3. 对所有的计数累加(从C中的第一个元素开始,每一项和前一项相加)
4. 反向填充目标数组:将每个元素i放在新数组的第C(i)项,每放一个元素就将C(i)减去1
参考链接:Wikipedia 计数排序
方法一:HashMap
public class Solution {
public void sortColors(int[] nums) {
if(nums == null || nums.length == 0)
return;
HashMap<Integer, Integer> map = new HashMap();
int len = nums.length;
for(int i = 0; i < len; i ++) {
if(map.containsKey(nums[i]))
map.put(nums[i], map.get(nums[i]) + 1);
else
map.put(nums[i], 1);
}
int red = 0;
int white = 0;
int blue = 0;
if(map.containsKey(0))
red = map.get(0);
if(map.containsKey(1))
white = map.get(1);
if(map.containsKey(2))
blue = map.get(2);
for(int i = 0; i < red; i ++)
nums[i] = 0;
for(int i = red; i < red + white; i ++)
nums[i] = 1;
for(int i = red + white; i < red + white + blue; i ++)
nums[i] = 2;
}
}
86 / 86 test cases passed.
Status: Accepted
Runtime: 300 ms
方法二:计数排序
public class Solution {
public void sortColors(int[] nums) {
if(nums == null || nums.length == 0)
return;
int len = nums.length;
int[] res = new int[len];
int[] temp = new int[3];
for(int i = 0; i < len; i ++)
temp[nums[i]] ++;
for(int i = 1; i < 3; i ++)
temp[i] = temp[i] + temp[i - 1];
for(int i = len - 1; i >= 0; i --) {
res[temp[nums[i]] - 1] = nums[i];
temp[nums[i]] --;
}
for(int i = 0; i < len; i ++)
nums[i] = res[i];
}
}
86 / 86 test cases passed.
Status: Accepted
Runtime: 364 ms
方法三:只需要一次扫描,无需消耗额外空间
参考了别人的做法:http://blog.csdn.net/linhuanmars/article/details/24286349
还是利用了颜色是三种这一点,道理其实也简单,就是搞两个指针,一个指在当前0的最后一个下标,另一个是指在当前1的最后一个下标(2不需要指针因为剩下的都是2了)。进行一次扫描,如果遇到0就两个指针都前进一步并进行赋值,如果遇到1就后一个指针前进一步并赋值。
public void sortColors(int[] A) {
if(A==null || A.length==0)
return;
int idx0 = 0;
int idx1 = 0;
for(int i=0;i<A.length;i++)
{
if(A[i]==0)
{
A[i] = 2;
A[idx1++] = 1;
A[idx0++] = 0;
}
else if(A[i]==1)
{
A[i] = 2;
A[idx1++] = 1;
}
}
}
86 / 86 test cases passed.
Status: Accepted
Runtime: 284 ms