美文网首页
快速查询第K个数的最终解法(PAT Stack)

快速查询第K个数的最终解法(PAT Stack)

作者: 小幸运Q | 来源:发表于2018-07-17 00:29 被阅读15次

鸣谢:https://blog.csdn.net/sinat_29278271/article/details/47291659


1. 树状数组法:

A[i]表示i的出现次数,C[i]表示小于等于它的lowbit个数的和,求sum只有log2(n)的复杂度,再加上使用了[1,maxnum]的二分查找,log2(n)log2(n)相比分块查找的根号N1在百万级的数据量的时候还是快了点。但是数组空间上开销会大那么一点。

但还是需要预定义maxnum,要不然向上update的时候没有上限会陷入死循环,而中途修改maxnum又会导致大量原先大于maxnum的C[i]未被修改。

#include<bits/stdc++.h>
using namespace std;
#define N 100000
#define lowbit(i) ((i)&(-i))
// 最大值
int maxnum=N;
// A表示该数出现的次数
int A[N]={0};
// C表示小于等于它的lowbit个数的和
int C[N]={0};

int K=0;
// 第K大的值

vector<int>v;
// 更新节点时对相关节点的操作
void update(int num,int v){
  int i,j;
  int length=num;
  while(length<=maxnum){
    C[length]+=v;
    length+=lowbit(length);
  }
}
// 对A和C数组的操作
void add(int num){
  A[num]++;
  update(num,1);
}
void del(int num){
  A[num]--;
  update(num,-1);
}
// 计算小于等于num的数组元素的和
int sumup(int num){
  int length=num;
  int sum=A[num];
  length--;
  while(length>0){
    sum+=C[length];
    length-=lowbit(length);
  }
  return sum;
}
// 计算区间内的和
int sumBetween(int start,int end){
  return sumup(end)-sumup(start-1);
}
void findMedian(){
  if(v.empty()){
    printf("Invalid\n");
    return;
  }
  // 获取目标K
  if(v.size()&1){
    K=(v.size()+1)/2;
  }
  else{
    K=v.size()/2;
  }
  // 不需要像分块那样一个一个试过去,因为树状数组的sumup肯定是上升的,
  // 只需要二分查找即可。如果分块法采用二分查找,因为需要遍历的元素较多,不划算。
  int l=1;
  int r=maxnum;
  while(l<r){
    // 当l==r时停止,二分查找到了最终解
    int mid=(l+r)/2;
    if(sumup(mid)>=K){
      r=mid;
    }
    else{
      l=mid+1;
    }
  }
  printf("%d\n",l);
  // 理论上返回l还是r都是一样的
}
void Pop(){
  if(v.empty()){
    printf("Invalid\n");
    return;
  }
  int num=v[v.size()-1];
  del(num);
  printf("%d\n",num);
  v.pop_back();
}
void Push(int num){
  v.push_back(num);
  add(num);
}
int main(){
  char cmd[100];
  int i,j,times=0;
  scanf("%d",&times);
  for(i=0;i<times;i++){
    scanf("%s",cmd);
    if(strcmp(cmd,"Pop")==0){
      Pop();
    }
    else if(strcmp(cmd,"PeekMedian")==0){
      findMedian();
    }
    else{
      int num;
      scanf("%d",&num);
      Push(num);
    }
  }
}

相关文章

  • 快速查询第K个数的最终解法(PAT Stack)

    鸣谢:https://blog.csdn.net/sinat_29278271/article/details/4...

  • leetcode 973. 最接近原点的 K 个点 三种解法

    1. 解法一:利用系统排序:取前面K个数 2.解法二堆排:维护K大小的大顶堆 3.快排:选取第K个元素位置

  • Swift-第K个数字

    题目:有些数的素因子只有3,5,7.请设计一个算法,找出其中第k个数. 解法一 k个数字一定是有第k-1个数字与3...

  • 力扣 215 数组中的第K个最大元素

    题意:给定一个数组,找到第k个最大的元素 思路:利用快速排序,快速定位第k大的元素,具体可看代码注释 思想:快速排...

  • 第一章 引论

    1.本书讨论的内容 设有一组N个数而要确定其中第K个最大者,称之为选择问题 一种解法 该问题的一种解法是将这N个数...

  • 寻找最小的 k 个数

    寻找最小的 k 个数 题目描述: 输入 n 个整数,输出其中最小的 k 个。 分析和解法: 解法一:排序输出 要求...

  • 06-20:刷题综合三:快排

    快排: 1、快速排序 2、快速排序寻找第K个大 3、最小的K个数 1、手写快排算法 class Solution:...

  • 2018-01-29

    区间k大数查询 问题描述 给定一个序列,每次询问序列中第l个数到第r个数中第K大的数是哪个。 输入格式 第一行包含...

  • Lua 快速排序

    快排 在一个数组中快速找出第K大的数

  • PAT-B 1091 N-自守数(C语言)

    题目 链接:PAT (Basic Level) Practice 1091 N-自守数 如果某个数 K 的平方乘以...

网友评论

      本文标题:快速查询第K个数的最终解法(PAT Stack)

      本文链接:https://www.haomeiwen.com/subject/ywuppftx.html