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;        
    }
};

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

相关推荐
刚学HTML1 小时前
leetcode 05 回文字符串
算法·leetcode
Yan.love1 小时前
开发场景中Java 集合的最佳选择
java·数据结构·链表
AC使者1 小时前
#B1630. 数字走向4
算法
冠位观测者1 小时前
【Leetcode 每日一题】2545. 根据第 K 场考试的分数排序
数据结构·算法·leetcode
古希腊掌管学习的神2 小时前
[搜广推]王树森推荐系统笔记——曝光过滤 & Bloom Filter
算法·推荐算法
qystca2 小时前
洛谷 P1706 全排列问题 C语言
算法
浊酒南街2 小时前
决策树(理论知识1)
算法·决策树·机器学习
就爱学编程2 小时前
重生之我在异世界学编程之C语言小项目:通讯录
c语言·开发语言·数据结构·算法
学术头条2 小时前
清华、智谱团队:探索 RLHF 的 scaling laws
人工智能·深度学习·算法·机器学习·语言模型·计算语言学
Schwertlilien3 小时前
图像处理-Ch4-频率域处理
算法