给定一个有n个对象(包括k种不同的颜色,并按照1到k进行编号)的数组,将对象进行分类使相同颜色的对象相邻,并按照1,2,...k的顺序进行排序。
您在真实的面试中是否遇到过这个题?
Yes
样例
给出colors=[3, 2, 2, 1, 4]
,k=4
, 你的代码应该在原地操作使得数组变成[1, 2, 2, 3, 4]
注意
不能使用代码库中的排序函数来解决这个问题
挑战
一个相当直接的解决方案是使用计数排序扫描2遍的算法。这样你会花费O(k)的额外空间。你否能在不使用额外空间的情况下完成?
解法:
此题的挑战在于如何不适用额外的空间来完成。我的解法是用colors数组来存每种颜色出现的次数,colors[k - 1]表示k颜色出现的次数(为负数),比如colors[0]=-2表示1颜色出现了2次。算法分两步,第一步遍历一遍计算出每种颜色出现的次数,第二步从尾到头的填充颜色(注意当前填充下标index=curK - 1的情况)。
class Solution {
/**
* @param colors: A list of integer
* @param k: An integer
* @return: nothing
*/
public void sortColors2(int[] colors, int k) {
for(int i = 0; i < colors.length; ) {
if(colors[i] <= 0) {
i++;
continue;
}
if(colors[colors[i] - 1] >= 0) {
int tmp = colors[i] - 1;
swap(colors, i, colors[i] - 1);
colors[tmp] = -1;
}
else {
colors[colors[i] - 1]--;
colors[i] = 0;
i++;
}
}
int index = colors.length - 1;
int curK = k;
while(index >= 0) {
while(colors[curK - 1] < 0) {
colors[index--] = curK;
if(index + 1 != curK - 1)
colors[curK - 1]++;
}
curK--;
}
}
private void swap(int[] colors, int b, int e) {
int tmp = colors[b];
colors[b] = colors[e];
colors[e] = tmp;
}
}