ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

#Leetcode 912 Sort an Array 快排 改进

2022-08-03 00:35:03  阅读:151  来源: 互联网

标签:Sort nums int 快排 while vector vec pivot Array


改进版快排,pivot 不再是左边第一个元素,而是正中间元素(或者随机)。

有一个比较坑的地方就是,在每一趟双指针完成所有交换后,需要判断 pivot 需不需要被交换。
比如 test case 1 2 4 3,第一趟开始时 pivot 是 2, 先动右边的指针 j, 找到第一个比 2 小的数也就是 1。此时 1 不应该和 2 交换,否则会打破“每趟交换后,pivot 左边的数比 pivot 小,右边的数则更大”这一规则。
出现这个问题的原因就是指针 j 穿过了 pivot,那么就不知道这一轮 1 是最终的 pivot, 还是 2 是最终的 pivot。需要把相遇点和旧 pivot 比较后才能得出结论。

class Solution {
public:
    vector<int> sortArray(vector<int>& nums) {
        if (nums.size() <= 1) return nums;
        if (is_sorted(nums.begin(), nums.end())) return nums;
        qsort(nums, 0, nums.size() - 1);
        return nums;
    }
    
private:
    void qsort(vector<int>& vec, int l, int r) {
        if (l >= r) return;
        
        int pivot = l + (r - l) / 2, x = vec[pivot], i = l, j = r;
        while (i < j) {
            while (i < j && vec[j] >= x) --j;
            while (i < j && vec[i] <= x) ++i;
            
            if (i != j) swap(vec[i], vec[j]);
        }
        
        // Maybe cross the pivot, so may exchange pivot
        if (j < pivot && vec[j] > x) swap(vec[pivot], vec[j]);
        if (j > pivot && vec[j] < x) swap(vec[pivot], vec[j]);
        
        // 此时相遇点是新的 pivot
        qsort(vec, l, j);
        qsort(vec, j+1, r);
    }
};

AcWing 的 Y 神给出了一个快排的模板,也挺好用,代码十分简洁,省去了判断 cross the pivot 后的各种处理, 两个指针相遇的位置就是最终 pivot 的位置。
不过也有比较细节的地方,比如:

  • 使用了 do while 避免越界
  • 不能在两个里层循环里面添加 i < j 的设定
  • 比较关系是严格的大/小于
  • 交换两个指针值的前提是 i < j

可以使用 test case 49 59 88 37 3 97 68 54 31 98 来分析这些细节。

class Solution {
public:
    vector<int> sortArray(vector<int>& nums) {
        if (nums.size() <= 1) return nums;
        
        qsort(nums, 0, nums.size() - 1);
        return nums;
    }
    
private:
    // ACWing Y 神的模板
    void qsort(vector<int>& q, int l, int r) {
        if (l >= r) return;
        
        int i = l - 1, j = r + 1;  // 从开区间往中间遍历
        int mid = l + (r - l) / 2, x = q[mid];
        while (i < j) {
            // 太坑了, 这两个 while 不能添加 i < j 的设定!
            // 手动模拟了一遍,发现如果增加了 i < j 的设定,那么 j 的位置会偏移 1, 从而使得找到的区间有偏差
            // 此时 i = j,但是 nums[i] = nums[j] > x,所以区间 [left, j] 包含了一个大于 x 的值
            do ++i; while(q[i] < x);
            do --j; while(q[j] > x);
            
            if (i < j) swap(q[i], q[j]);
        }
        
        qsort(q, l, j);
        qsort(q, j+1, r);
    }
};

标签:Sort,nums,int,快排,while,vector,vec,pivot,Array
来源: https://www.cnblogs.com/Bw98blogs/p/16545611.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有