描述
将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);
}
}
贴一个c++版
quick_sort里的return右边的时候,k是不是要改变呀
哦不用不用,前面if里的条件看错了
为什么不能 k==j的时候直接返回
为什么洛谷的第k小整数用模板只能ac一个数据,我看题目差不多啊
我也想知道
洛谷那题里相同大小的整数只算一次,和这题不一样。按照数据规模,可以在输入时去掉重复数字。
对的,我最后发现了,感谢感谢
什么意思啊
洛谷也不是啊,洛谷也没去重
如果k==j时,只能说明第k个数在j的左边(包括j),但左边如果不知一个数,他们不一定时有序的因为他是先i++do while,而不是while,j–,最后在交换(因为这样第j=k个数一定是第k大的,因为这种情况下,最后一次会与哨兵交换)
这个思路也不错~
没想到空降大佬,受宠若惊,哈哈
do-while循环为什么不判断i是否越界呢?如果第一个数字是当前最大的数,第一轮while下标不就越界了吗?
你忽略了等于的情况吧,等于的话也是不会往后走的
y 总好像采纳了 这个 方法,我看 视频 已经 是这个方法了。
y总视频时间戳是8月19,而且明显两方法不同
k-1,好思路
简单修改y总模版为这个思路
全网最清晰代码
https://www.acwing.com/solution/content/138598/
else return quickSort(j+1, r, k);
这里递归右半边界的时候比较与y总的模板为什么不用减去前半边界的个数啊。进入else不是已经说明第k个数右半边界么。第k个数不是相对于整个数组的么。没看懂,求教
你好,这个你弄明白了吗?
因为这个方法比较的是下标的位置,第k个数是有序之后下标为k-1的数,j是左边跟右边的分界点的下标
思路很不错哦,不过scanner挺容易超时的吧,数据大的时候
把它引入我的题解,嘿嘿,%%%
这样的超时怎么解决啊
试试bufferreader
为什么最后递归右半边界的时候还是传递的k,不是应该减去前半边界限的个数吗
您好,想问一下,为什么‘if(l >= r) return A[k];’这里返回的是A[K]?如果一开始就是l>=r?
#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++版本
没有看懂,为什么返回a[k]。快速选择没有保证序列的顺序,为什么a[k]是第k小的数?
我一开始就是这个思路
这样改进OK不,望指正
可以用二分答案的方法 $(O(n \log t))$,其中 $t$ 为值域
点这里
好思路!!,功能一样,思路上简化不少!
如果最后只剩一个数时,k等于2,还是k=0 啊
好思路