1. 程式人生 > 實用技巧 >2020-07-26

2020-07-26

329. 矩陣中的最長遞增路徑

題解: 記憶化搜尋,dp[i][j]代表以(i,j)結點為起點的最長遞增路徑。記憶化搜尋即可。

class Solution {
public:
    int dp[1000][1000];
    int dir[4][2] = {1,0,0,1,-1,0,0,-1};
    int dfs(int x, int y, vector<vector<int>>& matrix ){
        if(dp[x][y]) return dp[x][y];
        
        int &ans = dp[x][y];
        ans 
= 1; // 其本身為1 for(int i=0;i<4;i++){ int xx = x+dir[i][0], yy = y+dir[i][1]; if(xx<0||xx>=matrix.size() || yy<0 || yy>=matrix[0].size() || matrix[xx][yy]<=matrix[x][y]) continue; ans = max(ans, dfs(xx, yy,matrix)+1); } return ans; }
int longestIncreasingPath(vector<vector<int>>& matrix) { int ans = 0; for(int i=0;i<matrix.size();i++){ for(int j=0;j<matrix[0].size();j++){ dfs(i,j,matrix); ans = max(ans , dp[i][j]); } } return
ans; } };

5457. 和為奇數的子陣列數目

題解: 動態規劃,子陣列是連續的(哭出聲,周賽以為是不連續...)。 dp[i][0] 代表以arr[i]結尾的和為奇數的子陣列個數,dp[i][1] 代表以arr[i]結尾的和為偶數的子陣列個數。

則當arr[i]為奇數時, 以arr[i]結尾的奇陣列數量等於以arr[i-1]結尾的偶陣列數量+1 , 以arr[i]結尾的偶陣列數量等於以arr[i-1]結尾的奇陣列數量。

則當arr[i]為偶數時, 以arr[i]結尾的偶陣列數量等於以arr[i-1]結尾的偶陣列數量+1 , 以arr[i]結尾的奇陣列數量等於以arr[i-1]結尾的奇陣列數量。

class Solution {
public:
    int dp[100005][2]; // dp[i][0]代表以arr[i]結尾的子陣列中和為奇數的子陣列數目,dp[i][1]則為偶數的子陣列個數
    int numOfSubarrays(vector<int>& arr) {
        dp[0][0] = arr[0]%2;
        dp[0][1] = !(arr[0]%2);
        int ans = dp[0][0];
        for(int i=1;i<arr.size();i++){
            if(arr[i]%2){
                dp[i][0] = dp[i-1][1] + 1;
                dp[i][1] = dp[i-1][0];
            }else{
                dp[i][0] = dp[i-1][0] ;
                dp[i][1] = dp[i-1][1] + 1;
            }
            ans = (ans+dp[i][0])%1000000007;
        }
        return ans;
    }
};

5458. 字串的好分割數目

題解: 字首和+列舉斷點。

class Solution {
public:
    bool Hash[100005][26],Hash1[100005][26];
    int numSplits(string s) {
        if(s.size()==1) return 0;
        Hash[0][s[0]-'a'] = 1;
        for(int i=1;i<s.size();i++){
            for(int j=0;j<26;j++) Hash[i][j] = Hash[i-1][j];
            Hash[i][s[i]-'a'] = 1;
        }
        int len = s.size();
        Hash1[len-1][s[len-1]-'a'] = 1;
        for(int i=len-2;i>=0;i--){
            for(int j=0;j<26;j++) Hash1[i][j] = Hash1[i+1][j];
            Hash1[i][s[i]-'a'] = 1;
        }
        int ans = 0;
        for(int i=0;i<len-1;i++){
            int a = 0;
            for(int j=0;j<26;j++){
                a += Hash[i][j];
            }
            int b = 0;
            for(int j=0;j<26;j++){
                b += Hash1[i+1][j];
            }
            //printf("%d %d\n",a, b);
            if(a==b) ans++;
        }
        return ans;
    }
};

5459. 形成目標陣列的子陣列最少增加次數

題解: 貪心的去搞了,如果前一個數比後一個數小,那麼可以知道肯定後一個數肯定形成了新的一段,然後操作了(後一個數-前一個數)次,如果後一個數與前一個數相等或者比它小,那他們是可以放在一次操作裡面搞定的。

class Solution {
public:
    int minNumberOperations(vector<int>& target) {
        int ans = target[0];
        
        for(int i=1;i<target.size();i++){
            if(target[i-1] >= target[i]) continue;
            ans += target[i] - target[i-1];
            
        }
        return ans;
        
    }
};

5473. 燈泡開關 IV

題解: 除去前導0不用變,每一次0->1 或者 1->0 都是重新分段引起的,看變化了多少次即可。

class Solution {
public:
    int minFlips(string target) {
        int i = 0;
        while(i<target.size()){
            if(target[i]=='0') i++;
            else break;
        }
        target = target.substr(i);
        if(target.size()==0) return 0;
        int ans = 1;
        for(int i=1;i<target.size();i++){
            if(target[i]==target[i-1]) continue;
            ans++;
        }
        return ans;
    }
};

5474. 好葉子節點對的數量

題解: 我的做法可能不太簡潔。。。找到所有的葉子結點,儲存所有葉子的父節點,通過列舉每一對葉子,然後計算LCA。

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode() : val(0), left(nullptr), right(nullptr) {}
 *     TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
 *     TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
 * };
 */
class Solution {
public:
    
    int f[2000], levels[2000];
    vector <int> leaf;
    int cnt = 0;
    void find_leaf(TreeNode* root, int fa,int level){
        if(!root) return;
        f[++cnt] = fa;
        levels[cnt] = level;
        int now = cnt;
        if(root->left==NULL && root->right==NULL) leaf.push_back(now);
        find_leaf(root->left, now, level+1);
        find_leaf(root->right,now, level+1);
        
    }
    
    
    int countPairs(TreeNode* root, int distance) {
        find_leaf(root,0,0);
        int ans = 0;
        
        for(int i=0;i<leaf.size();i++){
            for(int j=i+1;j<leaf.size();j++){
                int p = leaf[i], q = leaf[j];
                int d = 0;
                if (levels[p] >levels[q]) swap(p, q);
                while (levels[p] < levels[q]) q = f[q], d++;
                while (p != q) {
                    p = f[p];
                    q = f[q];
                    d += 2;
                }
                if(d <= distance) ans++;
            }
        }
        return ans;
    }
};