LeetCode-75. Sort Colors

Description

Given an array with n objects colored red, white or blue, sort them in-place 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.

Example

Input: [2,0,2,1,1,0]
Output: [0,0,1,1,2,2]

Follow up

1.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.

2.Could you come up with a one-pass algorithm using only constant space?

Solution 1(C++)

class Solution {
public:
    void sortColors(vector<int>& nums) {
        int len=nums.size();
        for(int i=0; i<len; i++){
            for(int j=i+1; j<len; j++){
                if(nums[i]>nums[j]){
                    int temp=nums[i];
                    nums[i]=nums[j];
                    nums[j]=temp;
                }
            }
        }
    }
};

Solution 2(C++)

class Solution {
public:
    void sortColors(vector<int>& nums) {
        int left=0, right=nums.size()-1;
        while(left<right){
            for(int i=left; i<right; i++){
                if(nums[i]>nums[i+1]){
                    int temp=nums[i];
                    nums[i]=nums[i+1];
                    nums[i+1]=temp;
                }
            }
            right--;
            for(int i=right; i>left; i--){
                if(nums[i]<nums[i-1]){
                    int temp=nums[i];
                    nums[i]=nums[i-1];
                    nums[i-1]=temp;
                }
            }
            left++;
        }
    }
};

Solution 3(C++)

class Solution {
public:
    void sortColors(vector<int>& nums) {
        int len=nums.size();
        for(int i=0; i<len; i++){
            int min=i;
            for(int j=i+1; j<len; j++){
                if(nums[j]<nums[min]){
                    min=j;
                }
            }
            if(i!=min){
              int temp=nums[i];
                nums[i]=nums[min];
                nums[min]=temp;              
            }
        }
    }
};

Solution 4(C++)

class Solution {
public:
    void sortColors(vector<int>& nums) {
        int len=nums.size();
        for(int i=1, j; i<len; i++){
            int get=nums[i];
            for(j=i-1; j>=0 && nums[j]>get; j--){
                nums[j+1]=nums[j];
            }
            nums[j+1]=get;
        }
    }
};

Solution 5(C++)

class Solution {
public:
    void sortColors(vector<int>& nums) {
        int len=nums.size();
        for(int i=1; i<len; i++){
            int get=nums[i];
            int left=0, right=i-1;
            while(left<=right){
                int mid=left+(right-left)/2;
                if(nums[mid]>get) right=mid-1;
                else left=mid+1;
            }
            for(int j=i-1; j>=left; j--){
                nums[j+1]=nums[j];
            }
            nums[left]=get;
        }
    }
};

Solution 6(C++)

class Solution {
public:
    void sortColors(vector<int>& nums) {
        int len=nums.size();
        int h=0;
        while(h<=len){
            h = 3*h + 1;
        }
        while(h>=1){
            for(int i=1; i<len; i++){
                int get=nums[i], j;
                for(j=i-h; j>=0 && nums[j]>get; j -= h){
                    nums[j+h]=nums[j];
                }
                nums[j+h]=get;
            }
            h=(h-1)/3;
        }
    }
};

Solution 7(C++)

class Solution {
public:
    void Merge(vector<int>& nums, int left, int mid, int right){
        int len=right-left+1;
        vector<int> temp(len,0);
        int index=0;
        int i=left, j=mid+1;
        while(i<=mid && j<=right){
            temp[index++] = nums[i] <= nums[j] ? nums[i++]:nums[j++];
        }
        while(i<=mid){
            temp[index++] = nums[i++];
        }
        while(j<=right){
            temp[index++] = nums[j++];
        }
        for(int k=0; k<len; k++){
            nums[left++] = temp[k];
        }
    }

    void MergeSortRecursion(vector<int>& nums, int left, int right){
        if(left==right) return;
        int mid=left+(right-left)/2;
        MergeSortRecursion(nums, left, mid);
        MergeSortRecursion(nums, mid+1, right);
        Merge(nums, left, mid, right);
    }

    void sortColors(vector<int>& nums) {
        int len=nums.size();
        MergeSortRecursion(nums, 0, len-1);
    }
};

Solution 8(C++)

class Solution {
public:
    void Merge(vector<int>& nums, int left, int mid, int right){
        int len=right-left+1;
        vector<int> temp(len,0);
        int index=0;
        int i=left, j=mid+1;
        while(i<=mid && j<=right){
            temp[index++] = nums[i] <= nums[j] ? nums[i++]:nums[j++];
        }
        while(i<=mid){
            temp[index++] = nums[i++];
        }
        while(j<=right){
            temp[index++] = nums[j++];
        }
        for(int k=0; k<len; k++){
            nums[left++] = temp[k];
        }
    }

    void MergeSortIteration(vector<int>& nums, int len){
        int left, mid, right;
        for (int i = 1; i < len; i *= 2) {       // 子数组的大小i初始为1,每轮翻倍
            left = 0;
            while (left + i < len) {             // 后一个子数组存在(需要归并)
                mid = left + i - 1;
                right = mid + i < len ? mid + i : len - 1;// 后一个子数组大小可能不够
                Merge(nums, left, mid, right);
                left = right + 1;               // 前一个子数组索引向后移动
            }
        }
    }

    void sortColors(vector<int>& nums) {
        int len=nums.size();
        MergeSortIteration(nums, len);
    }

Solution 9(C++)

class Solution {
public:

    void Swap(vector<int>& nums, int i, int j){
        int temp=nums[i];
        nums[i]=nums[j];
        nums[j]=temp;
    }

    void Heapify(vector<int>& nums, int i, int size){
        int left_child = 2 * i + 1;
        int right_child = 2 * i + 2;
        int max=i;
        if (left_child < size && nums[left_child] > nums[max]) 
            max = left_child;
        if (right_child < size && nums[right_child] > nums[max]) 
            max = right_child;
        if (max != i){
            Swap(nums, i, max);     
            Heapify(nums, max, size);         
        }
    }

    int BuildHeap(vector<int>& nums, int n){           
        int heap_size = n;
        for (int i = heap_size / 2 - 1; i >= 0; i--) 
            Heapify(nums, i, heap_size);
        return heap_size;
    }

    void HeapSort(vector<int>& nums, int n){
        int heap_size = BuildHeap(nums, n);
        while(heap_size > 1){
            Swap(nums, 0, --heap_size);
            Heapify(nums, 0, heap_size);     
        }
    }

    void sortColors(vector<int>& nums) {
        int len=nums.size();
        HeapSort(nums, len);
    }
};

Solution 10(C++)

class Solution {
public:
    void Swap(vector<int>& nums, int i, int j){
        int temp = nums[i];
        nums[i] = nums[j];
        nums[j] = temp;
    }

    int Partition(vector<int>& nums, int left, int right){
        int pivot = nums[right];               // 这里每次都选择最后一个元素作为基准
        int tail = left - 1;                // tail为小于基准的子数组最后一个元素的索引
        for (int i = left; i < right; i++){
            if (nums[i] <= pivot){
                Swap(nums, ++tail, i);
            }
        }
        Swap(nums, tail + 1, right);           // 最后把基准放到前一个子数组的后边,剩下的子数组既是大于基准的子数组
                                            // 该操作很有可能把后面元素的稳定性打乱,所以快速排序是不稳定的排序算法
        return tail + 1;                    // 返回基准的索引
    }

    void QuickSort(vector<int>& nums, int left, int right){
        if (left >= right)
            return;
        int pivot_index = Partition(nums, left, right); // 基准的索引
        QuickSort(nums, left, pivot_index - 1);
        QuickSort(nums, pivot_index + 1, right);
    }

    void sortColors(vector<int>& nums) {
        QuickSort(nums, 0, nums.size()-1);
    }
};

后续更新

其他相关题目可参考:

算法分析

我借用这一道题,把排序的主要算法都学习了一遍。主要参考:
常用排序算法总结(一)

这里介绍的都是比较排序,还有非比较排序可以参考:
常用排序算法总结(二)

这排序肯定要用单独的一篇博客来系统整理一下了。毕竟太经典也太重要了。

程序分析

这个一定要多动手写几遍。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值