题目描述:
Given an array of n objects with k different colors (numbered from 1 to k), sort them so that objects of the same color are adjacent, with the colors in the order 1, 2, ... k.
Notice
You are not suppose to use the library's sort function for this problem.
Given colors=[3, 2, 2, 1, 4]
, k=4
, your code should sort colors in-place to [1, 2, 2, 3, 4]
.
A rather straight forward solution is a two-pass algorithm using counting sort. That will cost O(k) extra memory. Can you do it without using extra memory?
最简单的就是用一个map把每个color出现的次数存起来,然后在数组中重新分配就是了,这样做的extra memory就是O(k)。题目要求不用extra memory,那就需要利用原有array的空间了。这题不同于普通的sort题,在于它给了K,也就是给了数字的范围。那么可以想到用数组前k个数字与color number一一对应,比如,第一个数对应color1,第二个数对应color2,...这样做的好处是我们可以利用index来判断color的值,那么数组自己的value就可以存color出现的次数了(注意1~K不一定全都会出现在数组中,有些value可能是0)。得到这样的数组后,用two pointers的思想从数组的尾巴开始分配color的值,就可以得到最终答案了。
Mycode(AC = 25ms):
class Solution{
public:
/**
* @param colors: A list of integer
* @param k: An integer
* @return: nothing
*/
void sortColors2(vector<int> &colors, int k) {
// write your code here
// 1,2,3,4,2
if (colors.size() == 0) return;
// put the color number in the right position,
// i.e., 1st element = color 1, 2nd element = color 2, ...
for (int i = 0; i < colors.size(); i++) {
if (colors[i] != i + 1) {
swap(colors, i, colors[i] - 1);
}
}
// the first k elements store the count of
// colors for each color
for (int i = 0; i < colors.size(); i++) {
if (i < k) {
colors[i] = colors[i] == i+1 ? 1 : 0;
}
else {
colors[colors[i] - 1]++;
}
}
// get the sorted color array from tail
int idx = colors.size() - 1; // 3
for (int i = k - 1; i >= 0; i--) { // 2
int count = colors[i]; // 1
while (idx >= 0 && count > 0) {
colors[idx--] = i + 1; // ,4
count--;
}
}
}
void swap(vector<int> &colors, int i, int j) {
int tmp = colors[i];
colors[i] = colors[j];
colors[j] = tmp;
}
};