思路
遍历一次输入,将所有的元素添加至map< int, vector< int > >,由于map的key是排好序的,所以直接将value插入到nums即可。
另一种思路:维护3个变量left,mid和right。left之前的元素全部保证为0,right之后的元素全部保证为2,mid为当前正在遍历的元素的位置。left和mid从0开始,right从数组最后一个元素开始。如果mid所在位置元素是2,就将其与right所在位置的元素交换;如果mid指向的元素是0,就将其与left所在位置的元素交换。这种解法要注意边界条件是mid <= right,因为left和right只保证其前后的元素取值正确,并不保证left和right正在指向的元素的值正确。
这一题很容易想到使用left和right两个指针,left从左向右找到2,right从右向左找到0,然后交换left和right指向的值。如果输入中只有0和2,这种方法才是可行的。考虑使用mid指针在输入中寻找0或者2,如果找到2,就把这个2分发给right,如果找到0,就把这个0分发给left。这里并不直接使用left和right找0和2,而是用mid找0和2,left和right只作为接收方。因此,left左边的值都是0,right右边的值都是2,而left和mid之间的值,都是mid已经遍历过的,因此,left和mid之间的值都是1。而mid和right之间的值都是没有遍历过的,当mid小于等于right时,也就是说,此时所有的元素都已经遍历过了,可以退出循环。
代码
class Solution {
public:
void sortColors(vector<int>& nums) {
map<int, vector<int>> mp;
for (const auto &num : nums){
mp[num].push_back(num);
}
nums.clear();
for (auto e : mp) {
nums.insert(nums.end(), e.second.begin(), e.second.end());
}
}
};
class Solution {
public:
void sortColors(vector<int>& nums) {
if (nums.empty()) return ;
int left = 0, right = nums.size() - 1, mid = 0;
while (mid <= right) {
while(nums[mid] == 2 && mid < right) swap(nums[mid], nums[right--]);
while(nums[mid] == 0 && mid > left) swap(nums[mid], nums[left++]);
++mid;
}
}
};