每日(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;
    }
};

  

 

posted @ 2020-10-09 16:51  goldstine  阅读(112)  评论(0)    收藏  举报