力扣 912. 排序数组


一、题目描述

给你一个整数数组 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.快速排序

快速排序,时间复杂度 O ( n log ⁡ n ) O(n\log n) O(nlogn),空间复杂度 O ( log ⁡ n ) O(\log n) O(logn)

class Solution {
public:
    vector<int> sortArray(vector<int> &nums) {
        quickSort(nums, 0, nums.size() - 1);
        return nums;
    }

private:
    void quickSort(vector<int> &nums, int begin, int end) {
        if (begin < end) {
            int pivot = partition(nums, begin, end);
            quickSort(nums, begin, pivot - 1);
            quickSort(nums, pivot + 1, end);
        }
    }

    int partition(vector<int> &nums, int low, int high) {
        int pivot_num = nums.at(low);

        while (low < high) {
            while (low < high && nums.at(high) >= pivot_num) {
                high--;
            }
            nums.at(low) = nums.at(high);
            while (low < high && nums.at(low) <= pivot_num) {
                low++;
            }
            nums.at(high) = nums.at(low);
        }
        nums.at(low) = pivot_num;
        
        return low;
    }
};

2.堆排序

堆排序,时间复杂度 O ( n log ⁡ n ) O(n\log n) O(nlogn),空间复杂度 O ( 1 ) O(1) O(1)

class Solution {
public:
    vector<int> sortArray(vector<int> &nums) {
        buildMaxHeap(nums);
        for (int i = static_cast<int>(nums.size() - 1); i >= 0; i--) {
            swap(nums.at(0), nums.at(i));
            heapAdjust(nums, 0, i);
        }
        return nums;
    }

private:
    /**
     * 构建大根堆
     */
    void buildMaxHeap(vector<int> &nums) {
        for (int i = static_cast<int>(nums.size()) / 2 - 1; i >= 0; i--) {
            heapAdjust(nums, i, static_cast<int>(nums.size()));
        }
    }

    /**
     * 调整以root为根的二叉树
     * @param nums 存储二叉树元素的数组
     * @param root 根节点
     * @param len 包括根节点在内要调整的元素总数
     */
    void heapAdjust(vector<int> &nums, int root, int len) {
        int tmp = nums.at(root);  // 本轮需要被筛选的值

        /* 从root的孩子开始逐层向下调整 */
        for (int child = 2 * root + 1; child < len; child = 2 * child + 1) {
            /* 选取两个孩子中值较大的那个节点与父节点进行比较 */
            if ((child + 1) < len && nums.at(child + 1) > nums.at(child)) {
                child++;
            }

            /* 如果某一个孩子大于当前根节点,则将该孩子换到当前根上
             * 否则结束当前层的调整 */
            if (nums.at(child) > tmp) {
                nums.at(root) = nums.at(child);
                root = child;  // 提前准备下一层循环
            } else {
                break;
            }
        }

        /* 将筛选的值放到最终位置上 */
        nums.at(root) = tmp;
    }
};

3.二路归并排序

二路归并排序,时间复杂度 O ( n log ⁡ n ) O(n\log n) O(nlogn),空间复杂度 O ( n ) O(n) O(n)

class Solution {
public:
    vector<int> sortArray(vector<int> &nums) {
        supply.reset(new vector<int>(nums.size()));
        mergeSort(nums, 0, static_cast<int>(nums.size() - 1));
        return nums;
    }

private:
    void mergeSort(vector<int> &nums, int begin, int end) {
        if (begin < end) {
            int mid = (begin + end) / 2;
            mergeSort(nums, begin, mid);
            mergeSort(nums, mid + 1, end);
            merge(nums, begin, mid, end);
        }
    }

    /**
     * 将两个子数组合并为一个大数组
     * @param nums 数据
     * @param begin 第一个子数组的起始元素下标
     * @param mid 第一个子数组的结束元素下标,它后面一个元素即为第二个子数组的起始元素
     * @param end 第二个子数组的结束元素下标
     */
    void merge(vector<int> &nums, int begin, int mid, int end) {
        int front, back, i;


        /* 将数据从nums拷贝到辅助数组中 */
        for (i = begin; i <= end; i++) {
            supply->at(i) = nums.at(i);
        }

        /* 依次将两个子数组的最小值复制到大数组中 */
        for (front = begin, back = mid + 1, i = begin; front <= mid && back <= end; i++) {
            if (supply->at(front) < supply->at(back)) {
                nums.at(i) = supply->at(front++);
            } else {
                nums.at(i) = supply->at(back++);
            }
        }

        /* 处理剩余数据 */
        while (front <= mid) {
            nums.at(i++) = supply->at(front++);
        }
        while (back <= end) {
            nums.at(i++) = supply->at(back++);
        }
    }

private:
    unique_ptr<vector<int>> supply = nullptr;  // 辅助数组
};

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值