leecode 解题总结:75. Sort Colors

来源:互联网 发布:mac下最好的输入法 编辑:程序博客网 时间:2024/06/11 23:57
#include <iostream>#include <stdio.h>#include <vector>using namespace std;/*问题: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?分析:颜色摆放问题。红白蓝三种颜色代表的数组,分别对应012,现在要使得数组中相同颜色的相邻。不能使用系统自带的排序函数。举例:假设为01121002,可以从左边设置指针low ,右边设置指针high,先分析只有0和2的情况:那么应该是如果右边遇到2跳过,直到遇到0,然后将A[high] = A[low],这样就把右侧的0拷贝到左侧如果左边遇到0就跳过,如果遇到2,然后将A[low] = A[high],这样就把左侧的2拷贝到原先右侧中0的位置直到low = high,就结束现在多了一个1,关键是如果遇到1应该怎么处理,1正确的位置应该在0和2中间。如果右边遇到非2,就交换,左边遇到非0就交换,那么会造成1会来回被摆放。可能1最终还是插入在0与2之间,因此有问题。如果我再设置一个1对应的指针mid,那么mid和low,high之间应该如何处理无法处理。一种统计排序:数出0,1,2的个数,然后分别放置,需要遍历两遍。另一种解法:不断将2放在最右边,并减少最右边的范围,将0放在最左边,并增加最左边的范围。维护一个当前最左边的zero,最右边的second。牛逼,从本质上考虑:0和2的位置,通过不断更新最左边和最右边的位置,使得1最后在应该在的位置输入:8(数组元素个数)0 1 1 2 1 0 0 2输出:0 0 0 1 1 1 2 2关键:1 1】如果遇到把A[i] == 2的判断放在前面,那么最右边的元素能够交换的是0或1,   1.1】如果交换的是0,那么后续 A[i] == 0的条件会处理;然后0会和最左边的1交换(2不可能,因为如果可能遇到2的话之前已经处理过了)   1.2】如果交换的是1,那么后续A[i] == 0的条件不会处理,i++   因此上述情况都会使得变成0..01..12..2有序2】如果把A[i] == 0判断放在前面,那么可能当前A[i]会和2或者1交换   2.1】如果交换的是2,那么把2放到了i的位置,下面A[i] == 2的判断会成立,然后该2会和最右边的0或1交换,如果此时最右边为0   那么交换后i的位置又变成0,但是不会再处理这种情况,造成0的位置不正确也就是说:A[i] == 0判断放在前面,如果和2交换,2再和最右边的0交换,此时为0不会再处理;          A[2] == 2判断放在前面,如果和0交换,0会和最左边的1交换,不影响顺序2 int low = 0;int high = size - 1;for(int i = low ; i <= high ; i++){//这里带来一个问题是最右边如果本来就为2,就少了一个2的交换。这里如果两个交换元素都是2,则交换后原位置仍为2//然后原位置和新的最右边元素继续交换,直到最右边元素不是2,这样交换完了之后就达到了要求//注意2的判断需要放在0的前面,因为:2不断与最右边元素交换完了之后可能最右边元素恰好为0,然后后续进行0的交换while(2 == nums.at(i) && i < high){swap(nums.at(i) , nums.at(high--));}//碰到0,放在最左边,并更新low,之所以用while且i不变就是为了防止两个元素都是0,交换后了之后,没有改变,所以和后面的元素交换while(0 == nums.at(i) && i > low){swap(nums.at(i) , nums.at(low++));}}*/class Solution {public:    void sortColors(vector<int>& nums) {        if(nums.empty() || nums.size() == 1){return ;}int size = nums.size();int low = 0;int high = size - 1;for(int i = low ; i <= high ; i++){//这里带来一个问题是最右边如果本来就为2,就少了一个2的交换。这里如果两个交换元素都是2,则交换后原位置仍为2//然后原位置和新的最右边元素继续交换,直到最右边元素不是2,这样交换完了之后就达到了要求//注意2的判断需要放在0的前面,因为:2不断与最右边元素交换完了之后可能最右边元素恰好为0,然后后续进行0的交换while(2 == nums.at(i) && i < high){swap(nums.at(i) , nums.at(high--));}//碰到0,放在最左边,并更新low,之所以用while且i不变就是为了防止两个元素都是0,交换后了之后,没有改变,所以和后面的元素交换while(0 == nums.at(i) && i > low){swap(nums.at(i) , nums.at(low++));}}    }};void print(vector<int>& result){if(result.empty()){cout << "no result" << endl;return;}int size = result.size();for(int i = 0 ; i < size ; i++){cout << result.at(i) << " " ;}cout << endl;}void process(){ vector<int> nums; int value; int num; Solution solution; vector<int> result; while(cin >> num ) { nums.clear(); for(int i = 0 ; i < num ; i++) { cin >> value; nums.push_back(value); } solution.sortColors(nums); print(nums); }}int main(int argc , char* argv[]){process();getchar();return 0;}

0 0