首页 > 其他分享 >【NC207028】第k小数

【NC207028】第k小数

时间:2024-03-29 10:31:02浏览次数:20  
标签:ch int 元素 while 数组 pivot NC207028 小数

题目

第k小数

快速排序思想

思路

这道题有多种解法,这里记录一种个人认为最优的解法:基于快速排序的选择算法

基于快速排序的寻找数组中第 k k k 小元素的算法也称为快速选择算法。它的基本思想是,利用快速排序中的 p a r t i t i o n partition partition 函数将数组划分为若干个子数组,其中第一个子数组中的元素都小于等于一个特定的值 p i v o t pivot pivot,而第二个子数组中的元素都大于 p i v o t pivot pivot。如果第一个子数组中的元素的个数小于 k k k,那么我们就在第二个子数组中寻找第 k − m k-m k−m 大的元素,其中 m m m 是第一个子数组中元素的个数。如果第一个子数组中的元素的个数大于等于 k k k,那么我们就在第一个子数组中寻找第 k k k 小的元素。

需要注意的是,基于传统的快速排序算法要在给定数据是随机的情况下性能才好,对于人为构造的数据(卡时间的数据)来说性能不好,所以这里的快速选择算法是将随机化改进为了双指针以适应各种数据。

代码

#include <stdio.h>

#define N 5000005

// 快读
int read() {
    int x = 0, f = 1;
    char ch = getchar();
    while (ch < '0' || ch > '9') {
        if (ch == '-') f = -1;
        ch = getchar();
    }
    while (ch >= '0' && ch <= '9') {
        x = (x << 1) + (x << 3) + (ch ^ 48);
        ch = getchar();
    }
    return x * f;
}

/**
 * @brief 寻找数组中第k小的元素(k=0,1,2...)
 *
 * @param a 数组
 * @param start 起始位置(闭区间)
 * @param end 结束位置(闭区间)
 * @param k 第k小的元素(k=0,1,2...)
 * @return int 第k小的元素本身
 */
int quick_select(int* a, int start, int end, int k) {
    if (start == end) return a[start];
    int pivot = a[start], i = start - 1, j = end + 1;
    while (i < j) {
        do i++;
        while (a[i] < pivot);
        do j--;
        while (a[j] > pivot);
        if (i < j) {
            a[i] ^= a[j];
            a[j] ^= a[i];
            a[i] ^= a[j];
        }
    }
    if (k <= j) return quick_select(a, start, j, k);
    return quick_select(a, j + 1, end, k);
}

int main(void) {
    int t = 0;
    scanf("%d", &t);
    int n = 0, k = 0;
    int a[N], i = 0;
    while (t--) {
        scanf("%d%d", &n, &k);
        for (i = 0; i < n; i++) {
            a[i] = read();
        }
        printf("%d\n", quick_select(a, 0, n - 1, k - 1));
    }
    return 0;
}

标签:ch,int,元素,while,数组,pivot,NC207028,小数
From: https://blog.csdn.net/m0_52319522/article/details/137136895

相关文章

  • 输入8个整数放入一维数组w中,输出交换前的数组,找出其中的最大数和最小数并将他们分别与
    #include<stdio.h>intmain(){intw[8];inti,maxIndex=0,minIndex=0,temp;//用户输入8个整数printf("请输入8个整数:");for(i=0;i<8;i++){scanf("%d",&w[i]);}//假设第一个元素为最大和最小值......
  • java:欧拉公式e^ix==cosx+i*sinx 用Math类中的方法输出90°以内的欧拉函数数值,保留四位
    publicclassMain{//本题的要求:e^ix==cosx+i*sinxdoubleb,c;chari;publicstaticvoidmain(String[]args){for(doublej=0;j<90;j++){//用循环依次整出0-90度doublesum=0;//temp是e^ix;doublea=j;a=Math.toRadi......
  • 2605. 从两个数字数组里生成最小数字c
    intminNumber(int*nums1,intnums1Size,int*nums2,intnums2Size){intmin=INT_MAX;for(inti=0;i<nums1Size;i++){intsum=0;for(intj=0;j<nums2Size;j++){if(nums1[i]!=nums2[j]){if(nums1[i]>......
  • 每日一题:C语言经典例题之实数的小数部分
    题目描述输入一个实数,输出该实数的小数部分,小数部分若多余的末尾0,请去掉。如输入111111.12345678912345678900则输出0.123456789123456789。若去掉末尾0之后小数部分为0,则输出“Nodecimalpart”。注意该实数的位数不超过100位。输入输入一个实数。输出输出该实数的小......
  • 如何在数据库中存储小数:FLOAT、DECIMAL还是BIGINT?
    前言这里还是用前面的例子:在线机票订票系统的数据表设计。此时已经完成了大部分字段的设计,可能如下:CREATETABLEflights(flight_idINTAUTO_INCREMENTPRIMARYKEY,flight_numberVARCHAR(10),departure_airport_codeVARCHAR(3),arrival......
  • js-正负数保留小数点特定位数
    functionround(num,iCount){//iCount保留几位小数letchangeNum=numletzs=true//判断是否是负数if(changeNum<0){changeNum=Math.abs(changeNum)z......
  • Acwing255.第k小数
    可持久化权值线段树#include<iostream>#include<stdio.h>#include<algorithm>#include<string>#include<cmath>#include<cstring>#include<vector>#defineFor(i,j,n)for(inti=j;i<=n;++i)usingnamespace......
  • abc234E 不小于X的数位构成等差数列的最小数字
    给定X,求不小于X的整数,满足各个数位正好构成等差数列。1<=X<=1E17直接枚举首项和公差,找出所有可行的解,取最优值即可。#include<bits/stdc++.h>usingnamespacestd;#defineintlonglong#definerep(i,a,b)for(inti=a;i<=b;i++)#defineper(i,a,b)for(inti=b;i>=a;......
  • 分化小数
     输入正整数a,b,c,输出a/b的小数形式,精确到小数点后c位。a,b<=1000000,c<=100.输入包含多组数据,结束标记为a=b=c=0. #include<iostream>#include<iomanip>#include<sstream>intmain(){inta,b,c;std::stringresult;std::stringstreamss;......
  • 计算机进行小数运算时出错的原因
    首先,计算机进行小数运算时出错的原因可以归结为以下几个方面:精度限制:计算机内部使用二进制表示数据,而二进制无法精确表示所有的小数。这会导致在进行小数运算时,可能会产生舍入误差。例如,0.1在二进制中是一个无限循环小数,计算机只能近似表示,从而导致运算结果的不精确。舍入......