排序数组
  vwKuDCExiAAC 2023年11月19日 23 0


排序数组 

数组

C++

Java

Python

前言

本题你可以选择直接调用库函数来对序列进行排序,但意义不大。由于排序算法有很多,本文只介绍三种常见的基于比较的复杂度较低的排序。

方法一:快速排序

思路和算法

快速排序的主要思想是通过划分将待排序的序列分成前后两部分,其中前一部分的数据都比后一部分的数据要小,然后再递归调用函数对两部分的序列分别进行快速排序,以此使整个序列达到有序。

我们定义函数 randomized_quicksort(nums, l, r) 为对 nums 数组里 排序数组_递归

那么核心就是划分函数的实现了,划分函数一开始需要确定一个分界值(我们称之为主元 pivot),然后再进行划分。而主元的选取有很多种方式,这里我们采用随机的方式,对当前划分区间 排序数组_时间复杂度_02

整个划分函数 partition 主要涉及两个指针 排序数组_数组_03

  1. 排序数组_递归_04
  2. 排序数组_数组_05
  3. 排序数组_数组_06

我们每次移动指针 排序数组_数组_07

当 排序数组_递归_08

如下的动图展示了一次划分的过程,刚开始随机选了 排序数组_数组_09

C++

Java

class Solution {
    int partition(vector<int>& nums, int l, int r) {
        int pivot = nums[r];
        int i = l - 1;
        for (int j = l; j <= r - 1; ++j) {
            if (nums[j] <= pivot) {
                i = i + 1;
                swap(nums[i], nums[j]);
            }
        }
        swap(nums[i + 1], nums[r]);
        return i + 1;
    }
    int randomized_partition(vector<int>& nums, int l, int r) {
        int i = rand() % (r - l + 1) + l; // 随机选一个作为我们的主元
        swap(nums[r], nums[i]);
        return partition(nums, l, r);
    }
    void randomized_quicksort(vector<int>& nums, int l, int r) {
        if (l < r) {
            int pos = randomized_partition(nums, l, r);
            randomized_quicksort(nums, l, pos - 1);
            randomized_quicksort(nums, pos + 1, r);
        }
    }
public:
    vector<int> sortArray(vector<int>& nums) {
        srand((unsigned)time(NULL));
        randomized_quicksort(nums, 0, (int)nums.size() - 1);
        return nums;
    }
};

 

复杂度分析

  • 时间复杂度:基于随机选取主元的快速排序时间复杂度为期望 排序数组_数组_10
  • 空间复杂度:排序数组_数组_11

方法二:堆排序

预备知识

思路和算法

堆排序的思想就是先将待排序的序列建成大根堆,使得每个父节点的元素大于等于它的子节点。此时整个序列最大值即为堆顶元素,我们将其与末尾元素交换,使末尾元素为最大值,然后再调整堆顶元素使得剩下的 排序数组_时间复杂度_12

如下两个动图展示了对 [4, 6, 8, 5, 9] 这个数组堆排序的过程:

排序数组_时间复杂度_13

排序数组_数组_14

C++

Java

Python3

class Solution {
    void maxHeapify(vector<int>& nums, int i, int len) {
        for (; (i << 1) + 1 <= len;) {
            int lson = (i << 1) + 1;
            int rson = (i << 1) + 2;
            int large;
            if (lson <= len && nums[lson] > nums[i]) {
                large = lson;
            } else {
                large = i;
            }
            if (rson <= len && nums[rson] > nums[large]) {
                large = rson;
            }
            if (large != i) {
                swap(nums[i], nums[large]);
                i = large;
            } else {
                break;
            }
        }
    }
    void buildMaxHeap(vector<int>& nums, int len) {
        for (int i = len / 2; i >= 0; --i) {
            maxHeapify(nums, i, len);
        }
    }
    void heapSort(vector<int>& nums) {
        int len = (int)nums.size() - 1;
        buildMaxHeap(nums, len);
        for (int i = len; i >= 1; --i) {
            swap(nums[i], nums[0]);
            len -= 1;
            maxHeapify(nums, 0, len);
        }
    }
public:
    vector<int> sortArray(vector<int>& nums) {
        heapSort(nums);
        return nums;
    }
};

 

复杂度分析

  • 时间复杂度:排序数组_数组_15
  • 空间复杂度:排序数组_数组_16

方法三:归并排序

思路

归并排序利用了分治的思想来对序列进行排序。对一个长为 排序数组_数组_17

算法

定义 mergeSort(nums, l, r) 函数表示对 nums 数组里 排序数组_时间复杂度_18

  1. 递归调用函数 mergeSort(nums, l, mid) 对 nums 数组里 排序数组_递归_19
  2. 递归调用函数 mergeSort(nums, mid + 1, r) 对 nums 数组里 排序数组_时间复杂度_20
  3. 此时 nums 数组里 排序数组_数组_21
    线性归并的过程并不难理解,由于两个区间均有序,所以我们维护两个指针 排序数组_递归_22
    如果 nums[i] <= nums[j] ,那么我们就将 排序数组_递归_23
    这样能保证我们每次都是让两个区间中较小的数加入临时数组里,那么整个归并过程结束后 排序数组_数组_24

如下的动图展示了两个有序数组线性归并的过程:

排序数组_时间复杂度_25

函数递归调用的入口为 mergeSort(nums, 0, nums.length - 1),递归结束当且仅当 l >= r

C++

Java

Python3

class Solution {
    vector<int> tmp;
    void mergeSort(vector<int>& nums, int l, int r) {
        if (l >= r) return;
        int mid = (l + r) >> 1;
        mergeSort(nums, l, mid);
        mergeSort(nums, mid + 1, r);
        int i = l, j = mid + 1;
        int cnt = 0;
        while (i <= mid && j <= r) {
            if (nums[i] <= nums[j]) {
                tmp[cnt++] = nums[i++];
            }
            else {
                tmp[cnt++] = nums[j++];
            }
        }
        while (i <= mid) {
            tmp[cnt++] = nums[i++];
        }
        while (j <= r) {
            tmp[cnt++] = nums[j++];
        }
        for (int i = 0; i < r - l + 1; ++i) {
            nums[i + l] = tmp[i];
        }
    }
public:
    vector<int> sortArray(vector<int>& nums) {
        tmp.resize((int)nums.size(), 0);
        mergeSort(nums, 0, (int)nums.size() - 1);
        return nums;
    }
};

 

复杂度分析

  • 时间复杂度:排序数组_数组_26

排序数组_递归_27

根据主定理我们可以得出归并排序的时间复杂度为 排序数组_递归_28

  • 空间复杂度:排序数组_递归_29
  • 排序数组_数组_30
  • 排序数组_递归_31

 

class Solution:
    def merge_sort(self, nums, l, r):
        if l == r:
            return
        mid = (l + r) // 2
        self.merge_sort(nums, l, mid)
        self.merge_sort(nums, mid + 1, r)
        tmp = []
        i, j = l, mid + 1
        while i <= mid or j <= r:
            if i > mid or (j <= r and nums[j] < nums[i]):
                tmp.append(nums[j])
                j += 1
            else:
                tmp.append(nums[i])
                i += 1
        nums[l: r + 1] = tmp

    def sortArray(self, nums: List[int]) -> List[int]:
        self.merge_sort(nums, 0, len(nums) - 1)
        return nums

 
链接:https://leetcode.cn/problems/sort-an-array/solutions/178305/pai-xu-shu-zu-by-leetcode-solution/

  

class Solution:
    def max_heapify(self, heap, root, heap_len):
        p = root
        while p * 2 + 1 < heap_len:
            l, r = p * 2 + 1, p * 2 + 2
            if heap_len <= r or heap[r] < heap[l]:
                nex = l
            else:
                nex = r
            if heap[p] < heap[nex]:
                heap[p], heap[nex] = heap[nex], heap[p]
                p = nex
            else:
                break
        
    def build_heap(self, heap):
        for i in range(len(heap) - 1, -1, -1):
            self.max_heapify(heap, i, len(heap))

    def heap_sort(self, nums):
        self.build_heap(nums)
        for i in range(len(nums) - 1, -1, -1):
            nums[i], nums[0] = nums[0], nums[i]
            self.max_heapify(nums, 0, i)
            
    def sortArray(self, nums: List[int]) -> List[int]:
        self.heap_sort(nums)
        return nums

 
链接:https://leetcode.cn/problems/sort-an-array/solutions/178305/pai-xu-shu-zu-by-leetcode-solution/

 

 

 

给你一个整数数组 nums,请你将该数组升序排列。

 

示例 1:

输入:nums = [5,2,3,1]
输出:[1,2,3,5]

示例 2:

输入:nums = [5,1,1,2,0,0]
输出:[0,0,1,1,2,5]

 

提示:

  • 1 <= nums.length <= 5 * 104
  • -5 * 104 <= nums[i] <= 5 * 104

 

 

 

 

 

 

 

 

 

 

 

 

 

 



【版权声明】本文内容来自摩杜云社区用户原创、第三方投稿、转载,内容版权归原作者所有。本网站的目的在于传递更多信息,不拥有版权,亦不承担相应法律责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@moduyun.com

  1. 分享:
最后一次编辑于 2023年11月19日 0

暂无评论

推荐阅读
vwKuDCExiAAC