leetcode周賽(2020/04/26)

5392 分割字符

在這裏插入圖片描述

代碼

簡單題

class Solution {
public:
    int maxScore(string s) {
        int N = s.length();
        vector<int> dp0,dp1;
        dp0.resize(N);
        dp1.resize(N);
        for(int i =0;i<N;i++)
        {
            if(i==0)
            {
                dp0[0] = 0;
                dp1[0] = 0;
            }
            else{
                dp0[i] = dp0[i-1];
                dp1[i] = dp1[i-1];
            }
            if(s[i]=='0')
                dp0[i] ++;
            else dp1[i]++;
        }
        int maxi = 0;
        for(int i=0;i<N-1;i++)
        {
            if(dp0[i]+(dp1[N-1]-dp1[i])>maxi)
            {
                maxi = dp0[i]+dp1[N-1]-dp1[i];
            }
        }
        return maxi;
    }
};

5393.可獲得的最大點數

在這裏插入圖片描述

代碼

經典前綴和

class Solution {
public:
    int maxScore(vector<int>& cardPoints, int k) {
        vector<int> sum;
        int N = cardPoints.size();
        sum.resize(N+1);
        for(int i=0;i<N;i++)
        {
            sum[i+1] = sum[i] + cardPoints[i];
        }
        int ans = 0;
        for(int i=0;i<=k;i++)
        {
            int right = N-k+i;
            ans = max(ans, sum[N]-sum[right]+sum[i]);
        }
        return ans;
    }
};

5394. 對角線遍歷Ⅱ

在這裏插入圖片描述

暴力,複雜度O(n^2)超時
在這裏插入圖片描述
上圖思路轉載自鏈接

代碼

typedef pair<long long,int> P;
class Solution {
public:
    vector<int> findDiagonalOrder(vector<vector<int>>& nums) {
        vector<P> p;
        for(int i=0;i<nums.size();i++)
        {
            for(int j=0;j<nums[i].size();j++)
            {
                long long val = (long long)(i+j)*(long long)(i+j+1)/2+j+1;
                p.push_back(make_pair(val,nums[i][j]));
            }
        }
        sort(p.begin(),p.end());
        vector<int> ans;
        for(int i=0;i<p.size();i++)
            ans.push_back(p[i].second);
        return ans;
    }
};

5395. 帶限制的子序列和在這裏插入圖片描述

此題很容易想到遞推式dp[i] = max(dp[i],dp[i-j]+nums[i],nums[i])(for j=1;j<=k&&i-j>=0),複雜度KN,所以這樣做會超時。dp[i] = max(max(dp[i-j])+nums[i],nums[i]),所以其實我們只要知道dp[i-1]~dp[i-k]中的最大值。
所以考慮使用雙端隊列,隊列頭是dp[i]~dp[i-k]最大值的下標。

class Solution {
public:
    int constrainedSubsetSum(vector<int>& nums, int k) {
        int N = nums.size();
        vector<int> dp;
        dp.resize(N);
        dp[0] = nums[0];
        int ans = dp[0];
        deque<int> st;
        st.push_front(0);
        for(int i=1;i<N;i++)
        {
            dp[i] = max(nums[i],nums[i]+dp[st.front()]);
            if(i-st.front()==k)              
                st.pop_front();
            while(st.size()&&dp[st.back()]<dp[i])             //保持單調性
                st.pop_back();
            st.push_back(i);
            ans = max(ans,dp[i]);
        }
        return ans;
    }
};

然後呢,還可以用優先隊列

class Solution {
public:
    int constrainedSubsetSum(vector<int>& nums, int k) {
        int N = nums.size();
        vector<int> dp;
        dp.resize(N);
        dp[0] = nums[0];
        int ans = dp[0];
        priority_queue<pair<int,int> > que;
        que.push(make_pair(dp[0],0));
        for(int i=1;i<N;i++)
        {
            dp[i] = max(nums[i],nums[i]+que.top().first);
            while(que.size()&&i-que.top().second>=k)
                que.pop();
            que.push(make_pair(dp[i],i));
            ans = max(ans,dp[i]);
        }
        return ans;
    }
};
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章