leetcode912.排序数组的题解

题目描述:

题目要求在不使用任何内置函数的情况下解决问题,时间复杂度为 O(nlog(n))。

笔者使用了快速排序,但是直接使用最原始的快速排序,有些特殊的测试用例会超时。

1)如果数组本身基本有序,则使用原始快速排序算法选取基准的方式,时间复杂度会退化为O(n^2),所以这里使用了随机选取基准点的方式,代码为

int randomIndex = left + rand()%(right-left+1);

swap(nums, left, randomIndex);

2)如果数组中出现了重复元素,速度也会变慢,在得到基准元素、排序之后,在递归调用排序函数前,先去除位置与基准相近、值与基准相同的元素,为什么选取基准呢?笔者认为其他位置的元素不是特别固定,选取基准后、进行一轮排序后,基准前后的元素与基准之间的大小关系是固定的,如果数组中有元素重复,那么在固定基准及其位置后,前后与基准相同的元素与数组前面或后面的大小关系也是确定的,其位置也不用调整了。

所以,最终代码是在原始快速排序基础上加上了随机选取基准点、去除重复元素,代码如下所示:

cpp 复制代码
class Solution {
public:
    void swap(vector<int>& nums, int i, int j) {
        if(i == j) {
            return;
        }
        int temp = nums[i];
        nums[i] = nums[j];
        nums[j] = temp;
    }

    void quicksort(vector<int>& nums, int left, int right) {
        if(left == right) {
            return;
        }
        int i = left;
        int j = right;
        int randomIndex = left + rand()%(right-left+1);
        swap(nums, left, randomIndex);
        while(i < j) {
            while((i < j) && (nums[j] >= nums[left])) {
                j--;
            }
            while((i < j) && (nums[i] <= nums[left])) {
                i++;
            }
            swap(nums, i, j);
        }
        swap(nums, left, i);
        if(i-left > 1) {
            int left_pivot = i - 1;
            while((left_pivot > left) && (nums[left_pivot] == nums[i])) {
                left_pivot--;
            }
            quicksort(nums, left, left_pivot);
        }
        if(right-i > 1) {
            int right_pivot = i + 1;
            while((right_pivot < right) && (nums[right_pivot] == nums[i])) {
                right_pivot++;
            }
            quicksort(nums, right_pivot, right);
        }
    }

    vector<int> sortArray(vector<int>& nums) {
        srand(time(0));
        quicksort(nums, 0, nums.size()-1);
        return nums;        
    }
};

思考:经典算法、前人经验当然是很好的,能够解决大部分问题,但是总有新的未知的情况出现,那么如何改进经典算法解决现有问题就是一个有趣的事情,把前人的算法理解透彻、算法的每一步的作用、新问题给现有算法带来了哪些挑战、如何改进原有算法既能不影响对于原有测试用例的处理效果又能改进对于新问题的处理效果,怎么办呢,勤学好问、多思考、多见识,把有趣的问题想清楚、弄明白,不贪多求全,找准方向、方法,刻意训练。

相关推荐
万能程序员-传康Kk3 小时前
旅游推荐数据分析可视化系统算法
算法·数据分析·旅游
PXM的算法星球3 小时前
【并发编程基石】CAS无锁算法详解:原理、实现与应用场景
算法
ll7788113 小时前
C++学习之路,从0到精通的征途:继承
开发语言·数据结构·c++·学习·算法
烨然若神人~3 小时前
算法第十七天|654. 最大二叉树、617.合并二叉树、700.二叉搜索树中的搜索、98.验证二叉搜索树
算法
爱coding的橙子4 小时前
每日算法刷题Day2 5.10:leetcode数组1道题3种解法,用时40min
算法·leetcode
Akiiiira4 小时前
【数据结构】栈
数据结构
程序媛小盐4 小时前
贪心算法:最小生成树
算法·贪心算法·图论
Panesle4 小时前
分布式异步强化学习框架训练32B大模型:INTELLECT-2
人工智能·分布式·深度学习·算法·大模型
c6lala5 小时前
数据结构day1
数据结构
多多*5 小时前
算法竞赛相关 Java 二分模版
java·开发语言·数据结构·数据库·sql·算法·oracle