首页 > 编程语言 >随机选择算法

随机选择算法

时间:2023-12-16 23:55:26浏览次数:34  
标签:下标 边界 int 选择 算法 随机 等于 区间 数是

在一个无序数组中求第k大或者第k小的问题,要求时间复杂度是O(N),那么对于这两个问题只要解决一个另一个就解决了。因为求第一大可以转换成求第n小。

那么对于一个有100个元素的数组来说,我们要求第57小的数,那么它就是在求这个数组排好序之后下标在56的值,因为如果数组的元素没有重复的话,那么在下标0位置的数一定是第一小的数,第二小的数一定是在下标1位置的数。那么对于一个有重复元素的数组,也是一样的。我们并不是要求去掉重复元素之后第k小的元素,注意题目的意思。因此对于找第k小实际上就是返回数组从小到大排完序之后第k - 1个位置,例如[1, 1, 2, 3]求第二小的数,实际上就是求数组从小到大排序之后,下标1位置的数是什么,第2小的数是1,而不是2,因为不是求去重之后第k小的数,所以第一小的数是1,第二小的数还是1,第三小的数是2,第四小的数是3。那么分析完毕,就可以写code了。

解题思路

  1. 利用快速排序分区的思想来进行查找。
  2. 如果要找的下标在等于区间之中,那么直接返回等于区间的值就可以了。
  3. 如果要找的下标在等于区间的右边,那么只要在等于区间的右边找
  4. 如果要找的下标在等于区间的左边,那么只要在等于区间的左边找
  5. 重复以上步骤

代码实现

void partition(int *a, int l, int r, int key);//按照key来分区
void swap(int *a, int i, int j) {
	int t = a[i];
	a[i] = a[j];
	a[j] = t;
}
int left;//记录等于区间的左边界
int right;//记录等于区间的右边界

int findKthLargest(int* nums, int numsSize, int k) {    
    int l = 0;//初始化左边界
    int r = numsSize - 1;//初始化右边界
    int ans = 0;

    srand(time(0));

    k = numsSize - k;//找第k大的元素,等于找下标numsSize - k的值

    while(l <= r) {//如果区间中还有元素
        partition(nums, l, r, nums[l + rand() % (r - l + 1)]);//随机出来一个数来分区
        if (k < left) {//如果要找的下标在左边
            r = left - 1;//更新右边界,因为只能在左边了
        }
        else if (k > right) {//更新左边界,因为只能在右边了
            l = right + 1;//更新左边界,因为只能在右边了
        }
        else {//找到了
            ans = nums[left];//给ans赋值,并且跳出循环
            break;
        }
    }

    return ans;
}
void partition(int *a, int l, int r, int key)
{
    int lb = l;//等于区间的左边界
    int rb = r;//等于区间的右边界
    int i = l;//遍历的下标

    while(i <= rb) {//只要没有到大于区间 
		if (a[i] < key) {//下标i的数小于基准值,放在左边界里面 
			swap(a, lb++, i++);//把左边界的后一个数和下标i的值交换,然后左区间扩张,然后去看下一个数 
		}
		else if ( a[i] > key){//下标i的数大于基准值,放在右边界里面 
			swap(a, rb--, i);//把右边界的前一个数和下标i的值做交换,然后右区间扩张,但i不能动,因为当前i的值还没有访问过 
		}
		else {//下标i的数等于基准值,放在左右边界之间 
			i++;//直接加1
		}
	} 

    left = lb;//更新left的值
    right = rb;//更新right的值
}

这个代码的时间复杂度是O(N),这个也是用数学期望求解的时间复杂度,因为它用了随机。就只能用数学期望来估计时间复杂度。空间复杂度O(1)。

标签:下标,边界,int,选择,算法,随机,等于,区间,数是
From: https://www.cnblogs.com/lwj1239/p/17904453.html

相关文章

  • 代码随想录算法训练营第四天 | 24. 两两交换链表中的节点,19.删除链表的倒数第N个节点,
    一、24.两两交换链表中的节点题目链接:LeetCode24.两两交换链表中的节点学习前:思路:未新增虚拟结点。节点数为0,1,2需要另外讨论。当节点数>=2时,返回的head值为第2个节点,需要3个指针first、second、prev,分别是第一个节点和第二个节点,以及第一个节点的前节点。while(first......
  • Q-learning与Sarsa算法辨析
     这个是Q-learing的一个算法,根据代码,它就是,先设定训练100次,然后,给它一个随机的状态,这里我们假设状态6就是终点,那么走迷宫的时候,如果没走到6,就要一直走下去,,所以里面还要用到一个while循环,然后在每个状态的时候,找一个非负的动作,存储在数组里,(算是合理动作的集合吧),下一个状态的指针......
  • 数据结构与算法 第一章(48课时课程笔记)Data Structure and Algorithms
    数据结构基础知识 数据(Data):是对信息的一种符号表示。在计算机科学中是指所有能输入到计算机中并被计算机程序处理的符号的总称。数据元素(DataElement):是数据的基本单位,在计算机程序中通常作为一个整体进行考虑和处理。一个数据元素可由若干个数据项(DataItem)组成。数据......
  • BM25算法评估文本检索结果
    BM25算法评估文本检索结果的详细步骤如下:数据准备:收集文本数据集,包括标题、作者和内容等信息。文本预处理:对文本进行预处理操作以便进行后续计算。常见的预处理包括分词、去除停用词(如一些常见的虚词、标点符号等)、词干化(将词汇还原为其原始形式)等。可以使用自然语言处理(NLP)库如NLT......
  • 机器学习中的算法——K最邻近算法(KNN)
    1.KNN算法的定位KNN算法属于分类算法,所以它是有监督学习里面的一部分,且属于有监督学习里的分类问题KNN的计算量很大KNN理论上比较成熟且算法简单易懂,易实现2.KNN算法的核心简单地说---“近朱者赤,近墨者黑”进行分类的时候,即将被分类的这个样本的附近(特征空间中最邻近......
  • 算法学习Day4两两交换,链表相交,环形链表
    Day4两两交换,链表相交,环形链表ByHQWQF2023/12/16笔记24.两两交换链表中的节点给你一个链表,两两交换其中相邻的节点,并返回交换后链表的头节点。你必须在不修改节点内部的值的情况下完成本题(即,只能进行节点交换)。解法:迭代法迭代法使用了虚拟头节点的技巧,迭代法代码class......
  • Kafka日志压实算法
    概念介绍我们有时候可以把Kafka当作key、value数据库用(当然kafka中的消息可以不指定key)。__consumer_offsets这个topic的数据,就是典型的key、value数据。/usr/local/kafka2.8/bin/kafka-run-class.shkafka.tools.DumpLogSegments--deep-iteration--print-data-log--files......
  • 【教3妹学编程-算法题】反转二叉树的奇数层
    3妹:“你不是真正的快乐,你的笑只是你穿的保护色”2哥 :3妹还在唱五月天的歌啊,你不知道五月天假唱,现在全网都在骂呢。3妹:知道啊,可是关我什么事,这个歌的确好听啊。2哥 :嗯嗯,不错,还以为你是脑残粉,无论黑白都只管追星呢。3妹:我是只管追歌的,歌好听就行啦。2哥 :追哥?追哪个哥,难......
  • 机器学习的方法主要可以分为以下几类¹²³: 1. **监督学习**:在监督学习中,我们有一个
    机器学习的方法主要可以分为以下几类¹²³:1.**监督学习**:在监督学习中,我们有一个标记的数据集,我们的目标是训练一个模型,使其能够预测新数据的标签。常见的监督学习算法包括:  -线性回归  -逻辑回归  -支持向量机(SVM)  -最近邻居(KNN)  -决策树......
  • KMP算法和Manacher算法
    KMP算法KMP算法解决的问题KMP算法用来解决字符串匹配问题:找到长串中短串出现的位置.KMP算法思路暴力比较与KMP的区别暴力匹配:对长串的每个位,都从头开始匹配短串的所有位.KMP算法:将短字符串前后相同的部分存储在\(next\)数组里,让之前匹配过的信息指导之后的匹配.......