每日(5)题(2020/10/9)
(1)枚举的方式影响时间复杂度
股票的最大价格:
假设把某股票的价格按照时间先后顺序存储在数组中,请问买卖 一次 该股票可能获得的利润是多少?
例如一只股票在某些时间节点的价格为[9, 11, 8, 5, 7, 12, 16, 14]。
如果我们能在价格为5的时候买入并在价格为16时卖出,则能收获最大的利润11。
class Solution {
public:
int maxDiff(vector<int>& nums) {
/* int res=0;
for(int i=0;i<nums.size();i++){
for(int j=i;j<nums.size();j++){
res=max(res,nums[j]-nums[i]);
}
}
return res;
*/
//方式二:枚举的方式,方式一是枚举买入的时间点,然后枚举卖出的时间点,
//方式二枚举卖出的时间点,并且在枚举卖出时记录买入的最小价格的时间点O(n)
if(nums.empty()||nums.size()==1){
return 0;
}
int minv=nums[0];
int res=0;
for(int i=1;i<nums.size();i++){
minv=min(minv,nums[i]);
res=max(res,nums[i]-minv);
}
return res;
}
};
(2)<queue>q q.front()返回队列第一个元素的下标引用,q.back()返回队列最后一个元素的下标引用,q.pop_back(),q.pop_front() 分别为删除最后一个元素和第一个元素。
https://www.cnblogs.com/aiguona/p/7281739.html 双端队列可以在首尾都可以添加和删除元素操作
q.push_front() q.push_back() 首尾添加元素
滑动窗口的最大值 ----------------------------------------------- 使用双端队列求滑动窗口的最大值
给定一个数组和滑动窗口的大小,请找出所有滑动窗口里的最大值。
例如,如果输入数组[2, 3, 4, 2, 6, 2, 5, 1]及滑动窗口的大小3,那么一共存在6个滑动窗口,它们的最大值分别为[4, 4, 6, 6, 6, 5]。
class Solution {
public:
vector<int> maxInWindows(vector<int>& nums, int k) {
vector<int>res;
deque<int>q;
for(int i=0;i<nums.size();i++){
if(!q.empty()&&(i-q.front()>=k)){
q.pop_front(); //判断窗口中元素的大小,超过则首部弹出
}
while(!q.empty()&&nums[i]>nums[q.back()]){
q.pop_back(); //保持双端队列的递减顺序
}
q.push_back(i);
if(i>=k-1){//当长度达到窗口大笑的时候,每移动一次都要输出一个窗口中的最大值
res.push_back(nums[q.front()]);
}
}
return res;
}
};
(3)扑克牌的顺子
方法一:先将扑克牌从小到大排序,统计0的个数,即大小王的个数,判断剩余的数如果存在对子,则不是顺子,然后如果相邻两个元素之间的差值如果查过0的个数,则没有顺子。
方法二,判断如果最大值-最小值<=4,则存在顺子,否则不存在顺子
class Solution {
public:
bool isContinuous( vector<int> numbers ) {
/* if(numbers.size()<5){
return false;
}
int zerocnt=0;
sort(numbers.begin(),numbers.end());
for(int i=0;i<numbers.size();i++){
if(numbers[i]==0){
zerocnt++;
}else{
if(numbers[i+1]-numbers[i]-1>zerocnt){
return false;
}
if((i+1<numbers.size())&&(numbers[i]==numbers[i+1])){
return false;
}
zerocnt-=(numbers[i+1]-numbers[i]-1);
}
}
return true;
*/
//方式二
if(numbers.size()<5){
return false;
}
int zerocnt=0;
sort(numbers.begin(),numbers.end());
while(zerocnt<numbers.size()&&numbers[zerocnt]==0){
zerocnt++;
}
if(zerocnt>4){
return false;
}
for(int i=zerocnt;i+1<numbers.size();++i){
if(numbers[i+1]==numbers[i]){
return false;
}
}
return numbers[numbers.size()-1]-numbers[zerocnt]<=4;
}
};
(4) 求输入序列中的中位数 大小堆的应用 堆是基于优先队列的priority_queue
priority_queue<int>maxHeap;
priority_queue<int,vector<int>,greater<int>>minHeap;
题目描述
如何得到一个数据流中的中位数?
如果从数据流中读出奇数个数值,那么中位数就是所有数值排序之后位于中间的数值。
如果从数据流中读出偶数个数值,那么中位数就是所有数值排序之后中间两个数的平均值。
样例
输入:1, 2, 3, 4
输出:1,1.5,2,2.5
解释:每当数据流读入一个数据,就进行一次判断并输出当前的中位数。
通过大根堆存储排序数组的前n/2或n/2+1个元素,则前面一般元素的最大值在大根堆的根节点上,即中位数
通过小根堆存储排序数组的后n/2个元素,则后面元素的最小值在小根堆的根节点上
class Solution {
public:
void insert(int num){
maxHeap.push(num);
//调整个数
if(maxHeap.size()>minHeap.size()+1){
int t=maxHeap.top();
maxHeap.pop();
minHeap.push(t);
}
//调整大小 一定要判断小根堆里是否有元素,
if(minHeap.size()&&maxHeap.top()>minHeap.top()){
int t1=maxHeap.top();
int t2=minHeap.top();
//删除大小堆堆顶元素
maxHeap.pop();
minHeap.pop();
minHeap.push(t1);
maxHeap.push(t2);
}
}
double getMedian(){
int n1=maxHeap.size();
int n2=minHeap.size();
if(n1==n2){
return (maxHeap.top()+minHeap.top())/2.0;
}else{
return maxHeap.top();
}
}
private:
priority_queue<int>maxHeap;
priority_queue<int,vector<int>,greater<int>>minHeap;
};
(5) 输入n个整数,找出其中最小的k个数。 复习排序算法
class Solution {
public:
vector<int> getLeastNumbers_Solution(vector<int> input, int k) {
/*vector<int> res;
sort(input.begin(),input.end());
for(int i=0;i<k;i++){
res.push_back(input[i]);
}
return res;*/
//堆排序,构造一个只维护k个元素的大根堆,
priority_queue<int>maxHeap;
vector<int>res;
for(int i=0;i<input.size();i++){
maxHeap.push(input[i]);
if(maxHeap.size()>k){
maxHeap.pop();
}
}
for(int i=0;i<k;i++){
res.push_back(maxHeap.top());
maxHeap.pop();
}
reverse(res.begin(),res.end());
return res;
}
};

浙公网安备 33010602011771号