总结leetcode上sort colors题C++的5种解法

Leetcode上的一道水题:Sort Colors

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.

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?

下面列出了5种C++解法:

1. 利用STL multiset的自动排序, 但是要用到线性空间复杂度, 时间复杂度是红黑树的O(nlogn)
不过题目有说不要用stl的sort, 这样算作弊吧

class Solution {
public:
    void sortColors(int A[], int n) {
        multiset<int> m;
        int i;
        for(i=0; i<n; i++) {
            m.insert(A[i]);
        }
        i=0;
        for(multiset<int>::iterator it = m.begin(); i<n; i++, it++) {
            A[i] = *it;
        }
    }
};

2. 计数排序
因为范围已知,而且范围巨小,所以计数排序也可以,不过要计数要扫描一次,输出的时候还要扫描一次

class Solution {
public:
	void sortColors(int A[], int n) {
		const int COLORNUM = 3;
		int counts[COLORNUM] = { 0 }; // 记录每个颜色出现的次数
		for (int i = 0; i < n; i++)
			counts[A[i]]++;
		for (int i = 0, index = 0; i < COLORNUM; i++)
			for (int j = 0; j < counts[i]; j++)
				A[index++] = i;
	}
};

3. 双指针
左边的指针red跟踪red,右边的指针blue跟踪blue
用cur指针从左边向右边扫描,如果碰到red就换到左边,如果碰到blue就换到右边
如果即不是red也不是blue,cur就往后移动

class Solution {
public:
    void sortColors(int A[], int n) {
        int red =0, blue = n-1, cur = 0;        
        while(cur<=blue){
            if(A[cur] == 0)
				swap(A[cur++],A[red++]); 
            else if(A[cur] == 2){
                swap(A[cur], A[blue--]);
            }
            else cur++;
        }
    }
};

4.用patition函数 equal_to函数和bind1st or bind2nd

class Solution {
public:
    void sortColors(int A[], int n) {
        partition(partition(A, A + n, bind1st(equal_to<int>(), 0)), A + n,
                    bind1st(equal_to<int>(), 1));
    }
};

or

class Solution {
public:
    void sortColors(int A[], int n) {
        partition(partition(A, A + n, bind2nd(equal_to<int>(), 0)), A + n,
                    bind2nd(equal_to<int>(), 1));
    }
};

5. 重新实现partition(), 这里C++11的patition使用的是前向迭代器, 而C++98使用的是双向迭代器
ForwardIterator是前向迭代器模板,pred是函数模板,Unary是指只接受一个参数,predicate是指
这个函数是用来预测的,返回bool类型,可以看出,patition的作用是凡是pred返回true的元素一律
交换到容器前半部分,返回的位置是后半部分的第一个元素,而不是前半部分的最后一个元素

class Solution {
public:
	void sortColors(int A[], int n) {
		partition(partition(A, A + n, bind1st(equal_to<int>(), 0)), A + n,
		bind1st(equal_to<int>(), 1));
	}
	private:
	template<typename ForwardIterator, typename UnaryPredicate>
	ForwardIterator partition(ForwardIterator first, ForwardIterator last,UnaryPredicate pred){
		auto pos = first;
		for (; first != last; ++first)
			if (pred(*first))
				swap(*first, *pos++);
		return pos;
	}
};


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值