• [LeetCode] 912. Sort an Array 数组排序



    Given an array of integers `nums`, sort the array in ascending order.

    Example 1:

    Input: [5,2,3,1]
    Output: [1,2,3,5]
    

    Example 2:

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

    Note:

    1. 1 <= A.length <= 10000
    2. -50000 <= A[i] <= 50000

    这道题让我们给数组排序,在平时刷其他题的时候,遇到要排序的时候,一般都会调用系统自带的排序函数,像 C++ 中直接就调用 sort 函数即可,但是这道题考察的就是排序,再调用系统的排序函数就有些说不过去了。这里需要自己实现排序功能,常见排序方法有很多,插入排序,选择排序,堆排序,快速排序,冒泡排序,归并排序,桶排序等等。它们的时间复杂度不尽相同,这道题貌似对于平方级复杂度的排序方法会超时,所以只能使用那些速度比较快的排序方法啦。题目给定了每个数字的范围是 [-50000, 50000],并不是特别大,这里可以使用记数排序 Count Sort,在 LeetCode 中也有直接利用这个解法的题[Sort Colors](http://www.cnblogs.com/grandyang/p/4341243.html),建立一个大小为 100001 的数组 count,然后统计 nums 中每个数字出现的个数,然后再从0遍历到 100000,对于每个遍历到的数字i,若个数不为0,则加入 count 数组中对应个数的 i-50000 到结果数组中,这里的 50000 是 offset,因为数组下标不能为负数,在开始统计个数的时候,每个数字都加上了 50000,那么最后组成有序数组的时候就要减去,参见代码如下:
    解法一:
    class Solution {
    public:
        vector<int> sortArray(vector<int>& nums) {
        	int n = nums.size(), j = 0;
            vector<int> res(n), count(100001);
            for (int num : nums) ++count[num + 50000];
            for (int i = 0; i < count.size(); ++i) {
            	while (count[i]-- > 0) {
            		res[j++] = i - 50000;
            	}
            }
            return res;
        }
    };
    

    下面就是大名鼎鼎的快速排序了 Quick Sort,貌似 STL 中的内置 sort 函数就是基于快速排序的,只不过这里要自己写而已。在 LeetCode 中也有一道使用这个算法思想的题 [Kth Largest Element in an Array](http://www.cnblogs.com/grandyang/p/4539757.html)。快排的精髓在于选一个 pivot,然后将所有小于 pivot 的数字都放在左边,大于 pivot 的数字都放在右边,等于的话放哪边都行。但是此时左右两边的数组各自都不一定是有序的,需要再各自调用相同的递归,直到细分到只有1个数字的时候,再返回的时候就都是有序的了,参见代码如下:
    解法二:
    class Solution {
    public:
        vector<int> sortArray(vector<int>& nums) {
        	quickSort(nums, 0, (int)nums.size() - 1);
        	return nums;
        }
        void quickSort(vector<int>& nums, int start, int end) {
            if (start >= end) return;
            int pivot = nums[start], i = start + 1, j = end;
            while (i <= j) {
                if (nums[i] > pivot && nums[j] < pivot) {
                    swap(nums[i++], nums[j--]);
                }
                if (nums[i] <= pivot) ++i;
                if (nums[j] >= pivot) --j;
            }
            swap(nums[start], nums[j]);
            quickSort(nums, start, j - 1);
            quickSort(nums, j + 1, end);
        }
    };
    

    我们也可以使用混合排序 Merge Sort,在 LeetCode 中也有一道使用这个思想的题 [Count of Range Sum](http://www.cnblogs.com/grandyang/p/5162678.html)。混合排序的思想跟快速排序比较类似,但也不完全一样,这里其实是一种先对半分,一直不停的对半分,直到分到只有一个数字的时候返回,然后在返回的途中进行合并,合并的时候用到了一个临时数组 tmp,先将区间 [start, end] 中的数字按顺序存入这个临时数组 tmp 中,然后再覆盖原数组中的对应位置即可,参见代码如下:
    解法三:
    class Solution {
    public:
        vector<int> sortArray(vector<int>& nums) {
        	mergeSort(nums, 0, (int)nums.size() - 1);
        	return nums;
        }
        void mergeSort(vector<int>& nums, int start, int end) {
        	if (start >= end) return;
        	int mid = (start + end) / 2;
        	mergeSort(nums, start, mid);
        	mergeSort(nums, mid + 1, end);
        	merge(nums, start, mid, end);
        }
        void merge(vector<int>& nums, int start, int mid, int end) {
            vector<int> tmp(end - start + 1);
            int i = start, j = mid + 1, k = 0;
            while (i <= mid && j <= end) {
            	if (nums[i] < nums[j]) tmp[k++] = nums[i++];
            	else tmp[k++] = nums[j++];
            }
            while (i <= mid) tmp[k++] = nums[i++];
            while (j <= end) tmp[k++] = nums[j++];
            for (int idx = 0; idx < tmp.size(); ++idx) {
            	nums[idx + start] = tmp[idx];
            }
        }
    };
    

    Github 同步地址:

    https://github.com/grandyang/leetcode/issues/912


    类似题目:

    Kth Largest Element in an Array

    Sort Colors

    Count of Range Sum


    参考资料:

    https://leetcode.com/problems/sort-an-array/

    https://leetcode.com/problems/sort-an-array/discuss/319326/Java-merge-sort-implementation

    https://leetcode.com/problems/sort-an-array/discuss/293820/Easiest-and-fastest-solution.-O(10n)

    https://leetcode.com/problems/sort-an-array/discuss/280903/C%2B%2B-QuickSort-and-CountingSort-solutions


    [LeetCode All in One 题目讲解汇总(持续更新中...)](https://www.cnblogs.com/grandyang/p/4606334.html)
  • 相关阅读:
    CF 142B Tprimes
    CF 231A Team
    poj 2001 Shortest Prefixes ——字典树入门
    hdu 1039 Easier Done Than Said?
    poj 2528 Mayor's posters
    hdu 1061 Rightmost Digit
    poj 2503 Babelfish
    CF271 A. Beautiful Year
    poj 2752
    CF271 B. Prime Matrix
  • 原文地址:https://www.cnblogs.com/grandyang/p/11483981.html
Copyright © 2020-2023  润新知