leetcode 第 217 場周賽(vivo)

小胖胖胖豬發表於2020-11-30

單調棧
在這裡插入圖片描述

class Solution {
public:
    vector<int> mostCompetitive(vector<int>& a, int k) {
        int n=a.size(),*s=new int[n+1],top=0;
        vector<int>ans;
        for(int i=0;i<n;++i){
            while(top&&a[s[top]]>a[i]&&n-i+top-1>=k) --top;//要保證未曾入棧元素+棧裡元素>=k
            s[++top]=i;
        }
        int l=1;
        while(k--) ans.push_back(a[s[l++]]);//棧裡前k個就是要求的序列
        return ans;
    }
};

差分
在這裡插入圖片描述在這裡插入圖片描述
在這裡插入圖片描述
一定要注意的是nums[i]<=limit !!!
在這裡插入圖片描述
接下來就是差分,看target落在sum數軸哪個點,操作次數最少了。

class Solution {
public:
    int sum[400000];
    int minMoves(vector<int>& nums, int limit) {
        int n=nums.size(),mx=0;
        for(int i=0;i<n/2;++i){
            int a=nums[i],b=nums[n-i-1];
            if(a>b) swap(a,b);
            mx=max(mx,b);
            sum[1]+=2;
            --sum[1+a],--sum[a+b];
            ++sum[a+b+1],++sum[b+limit+1];
        }
        int ans=n;
        for(int i=2;i<=mx+limit;++i) sum[i]+=sum[i-1],ans=min(ans,sum[i]);
        return ans;
    }
};

思維 我確實想不出來
在這裡插入圖片描述在這裡插入圖片描述
我承認我解釋的很牽強,還不是因為我不能證明,只能感覺。
奇數只能變化一次,那就是*2,偶數可以變化好幾次,直到一直/2得到奇數了,如12->6->3; 那我們 [4,1,5,20,3] 可以變成[4,2,10,20,6] 變成[2,4,6,10,20],這樣變很好理解,因為這樣不會導致結果發生變化。 對於[2,4,6,10,20]這個序列,不變化的話偏移量為20-2=18. 我們想得到更小的偏移量,怎麼變化這個序列呢? 能想到的就是[2,4,6,10,10] (為什麼不前面的元素比如10,6除以2)呢,因為前面的元素除以2 也可以由[2,4,6,10]變過去, 然後 變成[2,4,5,6]-->[2,3,4,5],這時候就不能繼續變化了。

1. 首先5前面偶數/2沒有意義,最大值一直是5,前面/2可能會導致最小值更小,進而偏移量更大
2. 5*2 行嗎,5*2不就變回去了我們之前考慮過的序列或者捨棄不考慮的序列了嗎
變成考慮過的序列很好理解,變成被捨棄的序列是什麼意思呢?
比如[2,3,4,5]-->[2,3,4,10]就是由[2,4,6,10]變得,6/2不如10/2;
class Solution {
public:
    int minimumDeviation(vector<int>& nums) {
        int n=nums.size();
        set<int>s;
        for(int i=0;i<n;++i) s.insert((nums[i]&1)?nums[i]*2:nums[i]);
        int ans=*s.rbegin()-*s.begin();
        while(s.size()>=1&&(*s.rbegin())%2==0){
            int x=*s.rbegin();
            s.erase(x),s.insert(x/2);
            ans=min(ans,*s.rbegin()-*s.begin());
        }
        return ans;
    }
};

相關文章