• [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)
  • 相关阅读:
    ASP.NET AJAX Sys未定义的解决方法
    幽默中的人生哲理
    我们总是试图抹去一些东西,比如记忆。然而,一切只是徒然。
    在webbrowser中操作js弹出的对话框 以及触发其它事件····
    Asp.Net :写入 、读取 、 删除、追加cookie数组?
    揭开ASP.NET中Cookie编程的奥秘
    多线程调度例子·····················
    winform编程——做过ini配置文件创建文件、添加配置项,修改配置项,删除配置项
    C# 比较二个时间差。Environment.TickCount
     WebBrowser控件捕捉DHTML事件
  • 原文地址:https://www.cnblogs.com/grandyang/p/11483981.html
Copyright © 2020-2023  润新知