【优选算法】(第二十三篇)

目录

快速选择算法(medium)

题目解析

讲解算法原理

编写代码

最⼩的k个数(medium)

题目解析

讲解算法原理

编写代码


快速选择算法(medium)

题目解析

1.题目链接:. - 力扣(LeetCode)

2.题目描述

给定整数数组nums和整数k,请返回数组中第k个最⼤的元素。

请注意,你需要找的是数组排序后的第k个最⼤的元素,⽽不是第k个不同的元素。

你必须设计并实现时间复杂度为O(n)的算法解决此问题。

⽰例1:

输⼊:3,2,1,5,6,4,k=2

输出:5

⽰例2:

输⼊:3,2,3,1,2,4,5,5,6,k=4

输出:4

提⽰:

1<=k<=nums.length<=10^5

-10^4<=numsi<=10^4

讲解算法原理

解法(快速选择算法):

算法思路:

在快排中,当我们把数组「分成三块」之后: l, left left + 1, right - 1 right, r ,我们可以通过计算每⼀个区间内元素的「个数」,进⽽推断出我们要找的元素是在「哪⼀个区间」⾥⾯。

那么我们可以直接去「相应的区间」去寻找最终结果就好了。

编写代码

c++算法代码:

复制代码
class Solution
{
public:
 int findKthLargest(vector<int>& nums, int k) 
 {
 srand(time(NULL));
 return qsort(nums, 0, nums.size() - 1, k);
 }
 int qsort(vector<int>& nums, int l, int r, int k)
 {
 if(l == r) return nums[l];
 // 1. 随机选择基准元素
 int key = getRandom(nums, l, r);
 // 2. 根据基准元素将数组分三块
 int left = l - 1, right = r + 1, i = l;
 while(i < right)
 {
 if(nums[i] < key) swap(nums[++left], nums[i++]);
 else if(nums[i] == key) i++;
 else swap(nums[--right], nums[i]);
 }
 // 3. 分情况讨论
 int c = r - right + 1, b = right - left - 1;
 if(c >= k) return qsort(nums, right, r, k);
 else if(b + c >= k) return key;
 else return qsort(nums, l, left, k - b - c);
 }
 int getRandom(vector<int>& nums, int left, int right)
 {
 return nums[rand() % (right - left + 1) + left];
 }
};

java算法代码:

复制代码
class Solution
{
 public int findKthLargest(int[] nums, int k) 
 {
 return qsort(nums, 0, nums.length - 1, k);
 }
 public int qsort(int[] nums, int l, int r, int k) 
 {
 if(l == r) 
 {
 return nums[l];
 }
 // 1. 按照随机选择的基准元素,将数组分三块
 int key = nums[new Random().nextInt(r - l + 1) + l];
 int left = l - 1, right = r + 1, i = l;
 while(i < right) 
 {
 if(nums[i] < key) swap(nums, ++left, i++);
 else if(nums[i] == key) i++;
 else swap(nums, --right, i);
 }
 // 2. 分情况讨论
 int c = r - right + 1, b = right - left - 1;
 if(c >= k) return qsort(nums, right, r, k);
 else if(c + b >= k) return key;
 else return qsort(nums, l, left, k - b - c);
 }
 public void swap(int[] nums, int i, int j) 
 {
 int t = nums[i];
 nums[i] = nums[j];
 nums[j] = t;
 }
}

最⼩的k个数(medium)

题目解析

1.题目链接:. - 力扣(LeetCode)

2.题目描述

输⼊整数数组arr,找出其中最⼩的k个数。例如,输⼊4、5、1、6、2、7、3、8这8个数字,则最⼩的4个数字是1、2、3、4。

⽰例1:

输⼊:arr=3,2,1,k=2

输出:1,2或者2,1

⽰例2:

输⼊:arr=0,1,2,1,k=1

输出:0

限制:

0<=k<=arr.length<=10000

0<=arri<=10000

讲解算法原理

解法(快速选择算法):
算法思路:

在快排中,当我们把数组「分成三块」之后: l, left left + 1, right - 1 right, r ,我们可以通过计算每⼀个区间内元素的「个数」,进⽽推断出最⼩的k个数在哪些区间⾥⾯。

那么我们可以直接去「相应的区间」继续划分数组即可。

编写代码

c++算法代码:

复制代码
class Solution
{
public:
 vector<int> getLeastNumbers(vector<int>& nums, int k) 
 {
 srand(time(NULL));
 qsort(nums, 0, nums.size() - 1, k);
 return {nums.begin(), nums.begin() + k};
 }
 void qsort(vector<int>& nums, int l, int r, int k)
 {
 if(l >= r) return;
 // 1. 随机选择⼀个基准元素 + 数组分三块
 int key = getRandom(nums, l, r);
 int left = l - 1, right = r + 1, i = l;
 while(i < right)
 {
 if(nums[i] < key) swap(nums[++left], nums[i++]);
 else if(nums[i] == key) i++;
 else swap(nums[--right], nums[i]);
 }
 // [l, left][left + 1, right - 1] [right, r]
 // 2. 分情况讨论
 int a = left - l + 1, b = right - left - 1;
 if(a > k) qsort(nums, l, left, k);
 else if(a + b >= k) return;
 else qsort(nums, right, r, k - a - b);
 }
 int getRandom(vector<int>& nums, int l, int r)
 {
 return nums[rand() % (r - l + 1) + l];
 }
};

java算法代码:

复制代码
class Solution
{
 public int[] getLeastNumbers(int[] nums, int k) 
 {
 qsort(nums, 0, nums.length - 1, k);
 int[] ret = new int[k];
 for(int i = 0; i < k; i++)
 ret[i] = nums[i];
 return ret;
 }
 public void qsort(int[] nums, int l, int r, int k)
 {
 if(l >= r) return;
 // 1. 随机选择⼀个基准元素 + 数组分三块
 int key = nums[new Random().nextInt(r - l + 1) + l];
 int left = l - 1, right = r + 1, i = l;
 while(i < right)
 {
 if(nums[i] < key) swap(nums, ++left, i++);
 else if(nums[i] == key) i++;
 else swap(nums, --right, i);
 }
 // 2. 分类讨论
 int a = left - l + 1, b = right - left - 1;
 if(a > k) qsort(nums, l, left, k);
 else if(a + b >= k) return;
 else qsort(nums, right, r, k - a - b);
 }
 public void swap(int[] nums, int i, int j)
 {
 int t = nums[i];
 nums[i] = nums[j];
 nums[j] = t;
 }
}
相关推荐
2601_961875241 分钟前
法考备考计划表|学习计划|资料已整理
java·开发语言·学习·eclipse·tomcat·c#·hibernate
不忘不弃3 分钟前
计算pi的近似值
算法
码云骑士4 分钟前
12-GIL不是性能杀手(下)-绕过GIL的三种方案与决策树
算法·决策树·机器学习
一只齐刘海的猫6 分钟前
【Leetcode】无重复字符的最长子串
算法·leetcode·职场和发展
行智科技8 分钟前
FAST-LIVO2 源码精读(二):环境搭建与编译避坑
算法·ubuntu·自动驾驶·slam
重生之我是Java开发战士12 分钟前
【Java SE】多线程(三):单例模式,阻塞队列,线程池与定时器
java·javascript·单例模式
AI人工智能+电脑小能手15 分钟前
【大白话说Java面试题 第115题】【并发篇】第15题:说一下悲观锁和乐观锁的区别?
java·开发语言·面试
插件开发19 分钟前
vs2015 cuda c++ cdpSimplePrint范例,递归功能实现演示
linux·c++·算法
Tisfy19 分钟前
LeetCode 2130.链表最大孪生和:转数组 / 快慢指针+链表翻转(O(1))
算法·leetcode·链表·题解
心之伊始28 分钟前
Spring Boot Actuator + Micrometer 实战:自定义业务指标并接入 Prometheus 观测接口耗时
java·spring boot·prometheus·actuator·micrometer