目录
求两个数的最大公约数,欧几里得算法
#include <iostream>
using namespace std;
int change(int a, int b) {
if (a%b == 0)
return b;
else return (b, a%b);
}
int main() {
int a, b;
cin >> a >> b;
cout << change(a, b) << endl;
return 0;
}
数组不去重的最小k个数
给定一个长度为 n 的可能有重复值的数组,找出其中不去重的最小的 k 个数。例如数组元素是4,5,1,6,2,7,3,8这8个数字,则最小的4个数字是1,2,3,4(任意顺序皆可)。
数据范围:0≤k,n≤100000,数组中每个数的大小0≤val≤10000
要求:空间复杂度 O(n) ,时间复杂度 O(nlogn)
思路:使用快排排序
class Solution {
public:
int Partition(vector<int> &input,int low,int high){
auto pivot=input[low];
while(low<high){
while(low<high&&input[high]>=pivot) --high;
input[low]=input[high];
while(low<high&&input[low]<=pivot) ++low;
input[high]=input[low];
}
input[low]=pivot;
return low;
}
void Traverse(vector<int> &input,int low,int high){
if(low<high){
int pivot=Partition(input,low,high);
Traverse(input,low,pivot-1);
Traverse(input,pivot+1,high);
}
}
vector<int> GetLeastNumbers_Solution(vector<int> input, int k) {
if(k==0)
input.resize(0);
else{
Traverse(input,0,input.size()-1);
input.resize(k);
}
return input;
}
};
重点:
1.vector传参时要用引用,才能修改vector的值
2.修改vector的大小由resize()函数完成
3. vector中每一个都是向量,不能直接int i=input[low],用auto类型
数据流的中位数
如何得到一个数据流中的中位数?如果从数据流中读出奇数个数值,那么中位数就是所有数值排序之后位于中间的数值。如果从数据流中读出偶数个数值,那么中位数就是所有数值排序之后中间两个数的平均值。我们使用Insert()方法读取数据流,使用GetMedian()方法获取当前读取数据的中位数。
数据范围:数据流中数个数满足 1≤n≤1000 ,大小满足 1≤val≤1000
进阶: 空间复杂度 O(n) , 时间复杂度 O(nlogn)
思路:每次Insert就快排一次,所以时间复杂度不低
看其它同学:可以进行插入排序,堆排序
堆排序的思路:
假设[0 ... median - 1]
的长度为l_len
, [median + 1 ... arr.sise() - 1]
的长度为 r_len
.
1.如果l_len == r_len + 1
, 说明,中位数是左边数据结构的最大值
2.如果l_len + 1 == r_len
, 说明,中位数是右边数据结构的最小值
3.如果l_len == r_len
, 说明,中位数是左边数据结构的最大值与右边数据结构的最小值的平均值。
所以,GetMedian()操作算法过程为:
- 初始化一个大根堆,存中位数左边的数据,一个小根堆,存中位数右边的数据
- 动态维护两个数据结构的大小,即最多只相差一个
Insert()操作算法过程为:
- 当我们已经添加的数据个数为奇数个时,大顶堆的数据个数比小顶堆多一个,此时若要再添加一个数据,必定添加在小顶堆
Rmin
上,但是我们不知道当前添加的数是否大于中位数,故要先可插入Lmax
然后将Lmax
中的最大数放入Rmin
中,同时删除Lmax
中的最大数,即删除堆顶 - 当我们已经添加的数据个数为偶数个时,小顶堆的数据个数等于大顶堆,此时若要再添加一个数据,必定添加在大顶堆
Lmax
上,添加的手段和前者相同。
class Solution {
public:
priority_queue<int> Lmax;
priority_queue<int, vector<int>, greater<int> > Rmin;
int cnt = 0; //记录当前已经添加数据的个数
void Insert(int num) {
if(cnt & 1) {
//已经添加了奇数个,当前添加至Rmin
Lmax.push(num);
Rmin.push(Lmax.top()); Lmax.pop();
} else {
//已经添加了偶数个,当前添加至Lmin
Rmin.push(num);
Lmax.push(Rmin.top()); Rmin.pop();
}
cnt ++ ;
}
double GetMedian() {
if(cnt & 1) return Lmax.top(); //奇数
else return (Lmax.top() + Rmin.top()) / 2.0; //偶数
}
};
重点:
priority_queue<Type, Container, Functional>
Type为数据类型, Container为保存数据的容器,Functional为元素比较方式。
如果不写后两个参数,那么容器默认用的是vector,比较方式默认用operator<,也就是优先队列是大顶堆,队头元素最大。