AcWing
  • 首页
  • 课程
  • 题库
  • 更多
    • 竞赛
    • 题解
    • 分享
    • 问答
    • 应用
    • 校园
  • 关闭
    历史记录
    清除记录
    猜你想搜
    AcWing热点
  • App
  • 登录/注册

AcWing 786. 写一个和yxc大佬不同但差不多思想的方法,代码更简单    原题链接    简单

作者: 作者的头像   星丶空 ,  2019-09-13 00:10:49 ,  所有人可见 ,  阅读 33271


165


69

描述

将k值当做物理地址的值,比如第5个数其实就是数组4的位置,第2个数就是数组1的位置

每次只需要判断k在左区间还是右区间,一直递归查找k所在区间
最后只剩一个数时,只会有数组[k]一个数,返回数组[k]的值就是答案


import java.util.Scanner;

public class Main{
    static int N = 100010;
    static int[] A = new int[N];
    static int n, k;
    public static void main(String[] args){
        Scanner sc = new Scanner(System.in);
        n = sc.nextInt();
        k = sc.nextInt();
        for(int i = 0; i < n; i++) A[i] = sc.nextInt();

        System.out.println(quickSort(0, n-1, k-1));
    }

    public static int quickSort(int l, int r, int k){
        if(l >= r) return A[k];

        int x = A[l], i = l-1, j = r+1;
        while(i < j) {
            do i++; while(A[i] < x);
            do j--; while(A[j] > x);
            if(i < j) {
                int temp = A[i];
                A[i] = A[j];
                A[j] = temp;
            }
        }

        if(k <= j) return quickSort(l, j, k);
        else return quickSort(j+1, r, k);
    }
}

56 评论


用户头像
哇哈哈   2022-08-21 21:53      43    踩      回复

贴一个c++版

#include <iostream>
#include <vector>

using namespace std;
vector<int> a;


int quick_sort(int l, int r, int k) {
    if(l >= r) return a[k];

    int x = a[l], i = l - 1, j = r + 1;
    while (i < j) {
        do i++; while (a[i] < x);
        do j--; while (a[j] > x);
        if (i < j) swap(a[i], a[j]);
    }
    if (k <= j) return quick_sort(l, j, k);
    else return quick_sort(j + 1, r, k);
}

int main() {
    int n, k;
    cin >> n >> k;
    a = vector<int>(n, 0);
    for (int i = 0; i < n; i++) {
        cin >> a[i];
    }

    cout << quick_sort(0, n - 1, k - 1) << endl;

    return 0;
}
用户头像
冲凉冲   2023-04-19 18:51         踩      回复

quick_sort里的return右边的时候,k是不是要改变呀

用户头像
冲凉冲   2023-04-19 18:56    回复了 冲凉冲 的评论      1    踩      回复

哦不用不用,前面if里的条件看错了

用户头像
划船全靠浪   2023-07-02 18:25      6    踩      回复

为什么不能 k==j的时候直接返回

用户头像
好好学习_98   2023-07-12 23:26         踩      回复

为什么洛谷的第k小整数用模板只能ac一个数据,我看题目差不多啊

用户头像
雪下逢春   2023-07-13 22:25    回复了 划船全靠浪 的评论         踩      回复

我也想知道

用户头像
ppyy   2023-08-09 17:25    回复了 好好学习_98 的评论         踩      回复

洛谷那题里相同大小的整数只算一次,和这题不一样。按照数据规模,可以在输入时去掉重复数字。

用户头像
好好学习_98   2023-08-09 17:43    回复了 ppyy 的评论         踩      回复

对的,我最后发现了,感谢感谢

用户头像
thebeatles   2023-10-07 21:24    回复了 ppyy 的评论         踩      回复

什么意思啊

用户头像
thebeatles   2023-10-07 21:47    回复了 ppyy 的评论         踩      回复

洛谷也不是啊,洛谷也没去重

用户头像
南路   2024-03-26 23:29    回复了 划船全靠浪 的评论         踩      回复

如果k==j时,只能说明第k个数在j的左边(包括j),但左边如果不知一个数,他们不一定时有序的因为他是先i++do while,而不是while,j–,最后在交换(因为这样第j=k个数一定是第k大的,因为这种情况下,最后一次会与哨兵交换)


用户头像
yxc   2019-09-13 02:47      31    踩      回复

这个思路也不错~

用户头像
星丶空   2019-09-13 09:06      6    踩      回复

没想到空降大佬,受宠若惊,哈哈

用户头像
acwing_31922   2024-01-11 00:20      1    踩      回复

do-while循环为什么不判断i是否越界呢?如果第一个数字是当前最大的数,第一轮while下标不就越界了吗?

用户头像
派大大大星   2024-04-07 21:35    回复了 acwing_31922 的评论         踩      回复

你忽略了等于的情况吧,等于的话也是不会往后走的


用户头像
MQy   2022-04-11 13:53      7    踩      回复

y 总好像采纳了 这个 方法,我看 视频 已经 是这个方法了。

用户头像
派大大大星   2024-04-07 21:34         踩      回复

y总视频时间戳是8月19,而且明显两方法不同


用户头像
voidmian   2022-08-07 17:40      4    踩      回复

k-1,好思路


用户头像
这是空格   2023-04-03 23:12      2    踩      回复

简单修改y总模版为这个思路

#include <iostream>

using namespace std;
const int N = 100000 +10;
int q[N];

int   quick_sort(int q[],int l,int r,int k){
    if(l>=r) return q[l];
    int i=l-1,j=r+1,x=q[(r+l)>>1];
    while(i<j){
        do i++;while(q[i]<x);
        do j--;while(q[j]>x);
        if(i<j){
            swap(q[i],q[j]);
        }
    }

    // if(j-l+1>=k){
    //     return quick_sort(q,l,j,k);
    // }
    // else return quick_sort(q,j+1,r,k-(j-l+1));
    if(k<=j)return quick_sort(q,l,j,k);//继续找下标为k的数
    else return quick_sort(q,j+1,r,k);


}
int main(){
    int n,k;
    scanf("%d%d", &n, &k);
    for (int i = 0; i < n; i ++ ){
        scanf("%d", &q[i]);
    }
    cout<<quick_sort(q,0,n-1,k-1);//目的是找到下表为k-1的数


    return 0;
}


用户头像
不高兴的兽奶   2022-09-21 14:27      2    踩      回复

全网最清晰代码
https://www.acwing.com/solution/content/138598/


用户头像
gongjin   2025-03-24 20:42 · 北京      1    踩      回复

n+n/2+n/4+n/8+....~=2n


用户头像
cn在此   2024-03-15 21:22      1    踩      回复

else return quickSort(j+1, r, k);
这里递归右半边界的时候比较与y总的模板为什么不用减去前半边界的个数啊。进入else不是已经说明第k个数右半边界么。第k个数不是相对于整个数组的么。没看懂,求教

用户头像
RyuJeXu   2024-07-08 17:23      1    踩      回复

你好,这个你弄明白了吗?

用户头像
geyser   2024-10-03 05:58    回复了 RyuJeXu 的评论         踩      回复

因为这个方法比较的是下标的位置,第k个数是有序之后下标为k-1的数,j是左边跟右边的分界点的下标


用户头像
SolitudeAlma   2021-02-09 15:33      1    踩      回复

思路很不错哦,不过scanner挺容易超时的吧,数据大的时候

用户头像
SolitudeAlma   2021-02-09 15:33      2    踩      回复

把它引入我的题解,嘿嘿,%%%

用户头像
橡木   2022-12-04 11:42    回复了 SolitudeAlma 的评论         踩      回复

这样的超时怎么解决啊

用户头像
SolitudeAlma   2022-12-04 17:47    回复了 橡木 的评论         踩      回复

试试bufferreader

用户头像
dotasf   2025-02-23 22:19 · 广东    回复了 橡木 的评论         踩      回复

BufferedReader即可。


用户头像
小宝xb   2024-12-15 14:42         踩      回复

其实y总每次写的代码虽然不是最简单的,但却是最有用的,我学了很久感触挺深的。这个函数可以求在一个数组中任意区间【l, r】的第k小的数,这个挺通用的


用户头像
cn在此   2024-03-16 10:31         踩      回复

为什么最后递归右半边界的时候还是传递的k,不是应该减去前半边界限的个数吗


用户头像
若   2024-02-04 16:19         踩      回复

您好,想问一下,为什么‘if(l >= r) return A[k];’这里返回的是A[K]?如果一开始就是l>=r?


用户头像
RiKyyyyy   2024-01-25 23:54         踩      回复

#include [HTML_REMOVED]
using namespace std;

const int N = 1e6 + 10;

int n,k;
int q[N];

void quick_sort(int q[], int l, int r) {
if (l >= r) return;
int x = q[l];
int i = l - 1;//在左右两侧,是因为不可以直接指向i和j,否则下面的dowhile循环没办法判断第一个是否属于swap交换的范围
int j = r + 1;//其实这里是用双指针思想,利用两个不同的指针指向两个不同的位置,分别进行前进,观察好–和的位置
while (i < j) {
do i
; while (q[i] < x);
do j – ; while (q[j] > x);
if (i < j) swap(q[i],q[j]);
}
quick_sort(q, l, j);//利用递归思想处理杂乱的两方数组
quick_sort(q, j + 1, r);
}

int main () {
scanf(“%d %d”, &n,&k);
for (int i = 0; i < n; i++) {
scanf(“%d”, &q[i]);
}
quick_sort(q, 0, n - 1);
printf(“%d”,q[k-1]);

}
贴一个c++版本


用户头像
justone   2024-01-15 13:23         踩      回复


用户头像
justone   2024-01-15 13:23         踩      回复


用户头像
骐骥miracle   2023-10-10 22:22         踩      回复

没有看懂,为什么返回a[k]。快速选择没有保证序列的顺序,为什么a[k]是第k小的数?


用户头像
在杰难逃   2023-08-23 22:28         踩      回复

我一开始就是这个思路


用户头像
zwj_123   2023-08-14 23:42         踩      回复

这样改进OK不,望指正

#include <iostream>
using namespace std;
const int N = 1e6+10;

int n,k;
int q[N];

void quick_sort(int l,int r)
{
    //特殊情况
    if(l>=r) return;
    //分出左右
    int x=q[l+r>>1],i=l-1,j=r+1;
    while(i<j)
    {
        do i++;while(q[i]<x);
        do j--;while(q[j]>x);
        if(i<j) swap(q[i],q[j]);
    }
    //递归处理左右
    if(k<=j) quick_sort(l,j);//if判断
    else quick_sort(j+1,r);
}
int main()
{
    scanf("%d %d",&n,&k);
    k--;//位置减去
    for(int i=0;i<n;i++) scanf("%d",&q[i]);

    quick_sort(0,n-1);

    printf("%d",q[k]);
    return 0;
}

用户头像
Bingxiu   2023-07-07 18:29         踩      回复

可以用二分答案的方法 $(O(n \log t))$,其中 $t$ 为值域

点这里


用户头像
叶超   2023-05-10 11:42         踩      回复

好思路!!,功能一样,思路上简化不少!


App 内打开
你确定删除吗?
1024
x

© 2018-2025 AcWing 版权所有  |  京ICP备2021015969号-2
用户协议  |  隐私政策  |  常见问题  |  联系我们
AcWing
请输入登录信息
更多登录方式: 微信图标 qq图标 qq图标
请输入绑定的邮箱地址
请输入注册信息