您现在的位置是:首页 >技术教程 >力扣 912. 排序数组网站首页技术教程

力扣 912. 排序数组

呦,又写BUG呢 2024-09-23 12:01:06
简介力扣 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(nlog 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 begin, int end) {
        int pivot_num = nums.at(begin);

        while (begin < end) {
            while (begin < end && nums.at(end) >= pivot_num) {
                end--;
            }
            nums.at(begin) = nums.at(end);
            while (begin < end && nums.at(begin) <= pivot_num) {
                begin++;
            }
            nums.at(end) = nums.at(begin);
        }

        nums.at(begin) = pivot_num;
        return begin;
    }
};

2.堆排序

堆排序,时间复杂度 O ( n log ⁡ n ) O(nlog 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) {
                break;
            } else {
                nums.at(root) = nums.at(child);
                root = child;  // 提前准备下一层循环
            }
        }

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

3.二路归并排序

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

class Solution {
public:
    vector<int> sortArray(vector<int>& nums) {
        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 - begin) / 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) {
        vector<int> supply(nums.size());  // 辅助数组
        int i, before, after;

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

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

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

在这里插入图片描述

风语者!平时喜欢研究各种技术,目前在从事后端开发工作,热爱生活、热爱工作。