【Lintcode】143. Sort Colors II

题目地址:

https://www.lintcode.com/problem/sort-colors-ii/description

给定一个数组 A A A,再给定一个数 k k k A A A里面的数字都是 1 ∼ k 1\sim k 1k。要求将 A A A排序。

法1:计数排序。开一个长度为 k k k的数组,记录一下 1 ∼ k 1\sim k 1k每个数出现的次数,然后再把 A A A填起来即可。代码如下:

public class Solution {
    /**
     * @param colors: A list of integer
     * @param k:      An integer
     * @return: nothing
     */
    public void sortColors2(int[] colors, int k) {
        // write your code here
        if (colors == null || colors.length == 0) {
            return;
        }
        
        int[] count = new int[k];
        for (int color : colors) {
            count[color - 1]++;
        }
    
        int idx = 0;
        for (int i = 0; i < count.length; i++) {
            for (int j = 0; j < count[i]; j++) {
                colors[idx++] = i + 1;
            }
        }
    }
}

时间复杂度 O ( n ) O(n) O(n),空间 O ( k ) O(k) O(k)

法2:彩虹排序。类似于快速排序里的partition做法,取一个pivot,然后把小于和大于pivot的数放到两边,这样每次partition完都能确定一个数已经全部放到中间了(也就是放到分界点上了)。彩虹排序比普通快速排序的写法更优的点在于,当同一个数字出现多次的时候,彩虹排序排完一遍之后会把这个数字都连续的存放到中间。所以在重复数字非常多的时候,彩虹排序会更快一些。代码如下:

public class Solution {
    /**
     * @param colors: A list of integer
     * @param k: An integer
     * @return: nothing
     */
    public void sortColors2(int[] colors, int k) {
        // write your code here
        partition(colors, 0, colors.length - 1);
    }
    
    private void partition(int[] colors, int l, int r) {
        if (l >= r) {
            return;
        }
        
        int midCol = colors[l + (r - l >> 1)];
        // 开始彩虹排序,将小于midCol的数都放到左边,大于mideCol的数都放到右边;
        // 维护两个指针i和k都指向小于和大于midCol的数中最中间的那个的下标
        int i = l - 1, j = l, k = r + 1;
        while (j < k) {
            if (colors[j] < midCol) {
                swap(colors, ++i, j++);
            } else if (colors[j] > midCol) {
                swap(colors, --k, j);
            } else {
                j++;
            }
        }
        
        // 递归排序左右两边
        partition(colors, l, i);
        partition(colors, k, r);
    }
    
    private void swap(int[] nums, int i, int j) {
        int tmp = nums[i];
        nums[i] = nums[j];
        nums[j] = tmp;
    }
}

时间复杂度 O ( n log ⁡ k ) O(n\log k) O(nlogk),空间 O ( log ⁡ k ) O(\log k) O(logk)(递归栈深度。这里指的都是平均复杂度)。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值