考考大家,华为云公众号里展示的这个快排程序哪里错了 - V2EX
V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
请不要在回答技术问题时复制粘贴 AI 生成的内容
samhjn
V2EX    程序员

考考大家,华为云公众号里展示的这个快排程序哪里错了

  • &bsp;
  •   samhjn 2024-01-04 22:31:43 +08:00 2748 次点击
    这是一个创建于 644 天前的主题,其中的信息可能已经有所发展或是发生改变。

    华为云前几天公测了类 Github Copilot 的 CodeArts Snap 产品,并发了篇公众号文章展示其强大能力。

    先略过其中生成的测试用例 assertEqual(bin_to_octact("101",8)) 等等低级槽点以外,考考各位 V 友,CodeArts Snap 生成的这段快排是正确的吗?哪里错了?如何改正?

    //快速排序算法代码 void quickSort(int left, int right, vector<int>& arr) { int i = left, j = right; int pivot = arr[left]; while(i < j) { if(i < j) while(arr[i] < pivot) i++; while(arr[j] > pivot) j--; if (i < j) { swap(arr[i], arr[j]); } } if(left < j) quickSort(left, j, arr); if(i < right) 

    公众号原图

    第 1 条附言    2024-01-05 13:01:41 +08:00
    发完贴以后华为云公众号终于把错误的快排给撤下来了哈哈,但不知为何依然把满是错误的 bin_to_octave 的测试用例那张图留着,按说 bug 密度显然是那张图更高吧?
    第 2 条附言    2024-01-05 13:03:59 +08:00
    bin_to_octal
    写了两遍都写错了,我检讨
    19 条回复    2024-01-05 18:43:33 +08:00
    stevenshuang
        1
    stevenshuang  
       2024-01-04 23:38:17 +08:00 via iPhone
    8 1 2 3 8
    while 就是死循环了吧,i 和 j 都动不了
    joh
        2
    joh  
       2024-01-05 08:13:59 +08:00 via Android
    While 死循环,而且 while 里面第一个 if 有啥意义么…他在循环内部更改了 arr ,但是没有更新 pivot 数值。
    samhjn
        3
    samhjn  
    OP
       2024-01-05 09:11:39 +08:00 via iPhone
    @joh pivot 数值一定要更新吗?
    samhjn
        4
    samhjn  
    OP
       2024-01-05 09:12:31 +08:00 via iPhone
    @stevenshuang 是会死循环没错,那这份代码和正确的版本之间差了什么呢?
    hemingqiao
        5
    hemingqiao  
       2024-01-05 09:31:48 +08:00
    ```
    void qsort(vector<int>& arr, int l, int r) {
    if (l >= r) return;
    int x = arr[l + r >> 1], i = l - 1, j = r + 1;
    while (i < j) {
    do i++; while (arr[i] < x);
    do j--; while (arr[j] > x);
    if (i < j) swap(ar[i], arr[j]);
    }
    qsort(arr, l, j), qsort(arr, j + 1, r);
    }
    ```
    samhjn
        6
    samhjn  
    OP
       2024-01-05 09:47:35 +08:00 via iPhone
    @hemingqiao 这个版本显然也是有问题的,举个简单的反例:100 1 这种长度为 2 的逆序数组
    billccn
        7
    billccn  
       2024-01-05 09:55:37 +08:00
    @hemingqiao Quick sort 里面 pivot 在左边、右边、中间都可以的。

    真正的问题是`int i = left`这里,这把 pivot 也放进去了,那 `while(arr[i] < pivot) i++;` 一次也不会进循环体。
    dif
        8
    dif  
       2024-01-05 11:04:09 +08:00
    说不定在鸿蒙系统上就是正确的呢?手动狗头。
    hemingqiao
        9
    hemingqiao  
       2024-01-05 11:30:27 +08:00
    @samhjn 你跑一下试试呢?我在 leetcode 上的 912 提交通过之后才贴上来的
    AntiFraud
        10
    AntiFraud  
       2024-01-05 11:34:47 +08:00
    void quickSort(int left, int right, vector<int>& arr) {
    if (left >= right) return;

    int i = left, j = right;
    int pivot = arr[left]; // 选择 left 位置的元素作为枢轴,通常会选择中位数或随机元素作为枢轴以避免最坏情况的性能。
    while (i < j) {
    while (i < j && arr[j] > pivot) j--; // 从右向左找第一个小于等于 pivot 的数
    while (i < j && arr[i] < pivot) i++; // 从左向右找第一个大于等于 pivot 的数
    if (i < j) {
    swap(arr[i], arr[j]);
    i++;
    j--;
    }
    }
    swap(arr[left], arr[i]); // 将枢轴放到正确的位置

    quickSort(left, i - 1, arr); // 对左半部分进行快速排序
    quickSort(i + 1, right, arr); // 对右半部分进行快速排序
    }
    hemingqiao
        11
    hemingqiao  
       2024-01-05 11:39:57 +08:00
    @billccn 是啊,他贴的这个是有问题的
    samhjn
        12
    samhjn  
    OP
       2024-01-05 11:45:20 +08:00 via iPhone
    @hemingqiao 看错了抱歉,没注意到左右游标已经预先补偿了
    samhjn
        13
    samhjn  
    OP
       2024-01-05 12:23:49 +08:00 via iPhone
    @AntiFraud 看起来算法是 work 的,但是有没有语句或者条件是冗余的?
    joh
        14
    joh  
       2024-01-05 14:31:43 +08:00
    @samhjn 不需要.他这个算法问题怪怪的.7 楼说的对
    tramm
        15
    tramm  
       2024-01-05 15:29:08 +08:00
    @dif 有道理
    deagleWSJ
        16
    deagleWSJ  
       2024-01-05 17:15:47 +08:00
    1. 当数组存在重复元素时,可能会导致死循环。修改:i++和 j--循环条件判断改为<=
    2. i 初始从 left 开始,且 pivot=arr[left],会导致每次循环 i 和 j 总会有一个不动,pivot 值在 i 和 j 间换来换去。修改:i 从 left+1 开始,最后把 pivot 换到中间。
    3. pivot 直接取 left 值,对于接近倒序的的数组性能较差。修改:left~right 间的随机位置作为 pivot ,并换到 left
    deagleWSJ
        17
    deagleWSJ  
       2024-01-05 17:35:43 +08:00
    @billccn 交换 arr[i], arr[j]后下一次循环会进入 while(arr[i] < pivot) i++。真正的问题对于含有重复元素的数组排序,当 arr[i]和 arr[j]都等于 pivot 时会死循环。
    qwertty01
        18
    qwertty01  
       2024-01-05 18:00:09 +08:00
    大佬 强啊
    samhjn
        19
    samhjn  
    OP
       2024-01-05 18:43:33 +08:00 via iPhone
    @deagleWSJ 带等号就没问题了吗?
    关于     帮助文档     自助推广系统     博客     API     FAQ     Solana     5288 人在线   最高记录 6679       Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 42ms UTC 09:07 PVG 17:07 LAX 02:07 JFK 05:07
    Do have faith in what you're doing.
    ubao snddm index pchome yahoo rakuten mypaper meadowduck bidyahoo youbao zxmzxm asda bnvcg cvbfg dfscv mmhjk xxddc yybgb zznbn ccubao uaitu acv GXCV ET GDG YH FG BCVB FJFH CBRE CBC GDG ET54 WRWR RWER WREW WRWER RWER SDG EW SF DSFSF fbbs ubao fhd dfg ewr dg df ewwr ewwr et ruyut utut dfg fgd gdfgt etg dfgt dfgd ert4 gd fgg wr 235 wer3 we vsdf sdf gdf ert xcv sdf rwer hfd dfg cvb rwf afb dfh jgh bmn lgh rty gfds cxv xcv xcs vdas fdf fgd cv sdf tert sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf shasha9178 shasha9178 shasha9178 shasha9178 shasha9178 liflif2 liflif2 liflif2 liflif2 liflif2 liblib3 liblib3 liblib3 liblib3 liblib3 zhazha444 zhazha444 zhazha444 zhazha444 zhazha444 dende5 dende denden denden2 denden21 fenfen9 fenf619 fen619 fenfe9 fe619 sdf sdf sdf sdf sdf zhazh90 zhazh0 zhaa50 zha90 zh590 zho zhoz zhozh zhozho zhozho2 lislis lls95 lili95 lils5 liss9 sdf0ty987 sdft876 sdft9876 sdf09876 sd0t9876 sdf0ty98 sdf0976 sdf0ty986 sdf0ty96 sdf0t76 sdf0876 df0ty98 sf0t876 sd0ty76 sdy76 sdf76 sdf0t76 sdf0ty9 sdf0ty98 sdf0ty987 sdf0ty98 sdf6676 sdf876 sd876 sd876 sdf6 sdf6 sdf9876 sdf0t sdf06 sdf0ty9776 sdf0ty9776 sdf0ty76 sdf8876 sdf0t sd6 sdf06 s688876 sd688 sdf86