给定一个有n个对象(包括k种不同的颜色,并按照1到k进行编号)的数组,将对象进行分类使相同颜色的对象相邻,并按照1,2,...k的顺序进行排序。
您在真实的面试中是否遇到过这个题?
Yes
样例
给出colors=[3, 2, 2, 1, 4],k=4, 你的代码应该在原地操作使得数组变成[1, 2, 2, 3, 4]
注意
不能使用代码库中的排序函数来解决这个问题
挑战
一个相当直接的解决方案是使用计数排序扫描2遍的算法。这样你会花费O(k)的额外空间。你否能在不使用额外空间的情况下完成?
标签 Expand
相关题目 Expand
解题思路:
非常典型的计数排序。
1.新建一个辅助数组,长度为原数组的最大值。
比如 原数组 colors[ ] = {3, 2, 2, 1, 4 }
新建的辅助数组为 fz[ ] = {0,0,0,0} 长度为4.
2.遍历原数组,将所对应的值记录到辅助数组中
遍历后fz[ ] = {0,1,2,1,1}
再遍历fz数组,统计colors数组中的每一个数字,小于等于i的元素个数
fz[ ] = {0,1,3,4,5}
3.新建一个辅助数组res[ ],利用fz[ ]和原数组colors[ ],将colors中元素放入正确的位置,存储在res[ ]中
colors[ ]从后往前去遍历,,将colors中元素放入正确的位置
i = 4 colors[ 4 ] = 4 fz[ 4 ] = 5 color[ 5-1 ] = 4 fz[ 4 ] = 5-1 = 4;
以下参考资料十分的清楚的解释了计数排序:
http://blog.csdn.net/tanyujing/article/details/8534843
class Solution {
/**
* @param colors: A list of integer
* @param k: An integer
* @return: nothing
*/
public void sortColors2(int[] colors, int k) {
// write your code here
if(colors==null||0==colors.length) return;
int len = colors.length;
int[] help = new int[k+1];
for(int i=0;i<len;i++){
help[colors[i]]++;
}
for(int i=1;i<k+1;i++){
help[i] += help[i-1];
}
int[] res = new int[len];
for(int i=len-1;i>=0;i--){
int pos = help[colors[i]];
help[colors[i]]--;
res[pos-1] = colors[i];
}
for(int i=0;i<len;i++){
colors[i] = res[i];
}
}
}