1. 程式人生 > 實用技巧 >Leetcode BiWeekly Contest 31

Leetcode BiWeekly Contest 31

  1. 在區間範圍內統計奇數數目
    給你兩個非負整數 low 和 high 。請你返回 low 和 high 之間(包括二者)奇數的數目。
    示例 1:
    輸入:low = 3, high = 7
    輸出:3
    解釋:3 到 7 之間奇數數字為 [3,5,7] 。
    示例 2:
    輸入:low = 8, high = 10
    輸出:1
    解釋:8 到 10 之間奇數數字為 [9] 。
    提示:
    0 <= low <= high <= 10^9

小學數學


class Solution {
public:
    int countOdds(int low, int high) {
        int ans = (high-low+1+1)>>1;
        if((low&1)||(high&1))
            return ans;
        return ans-1;
    }
};
  1. 和為奇數的子陣列數目
    給你一個整數陣列 arr 。請你返回和為 奇數 的子陣列數目。
    由於答案可能會很大,請你將結果對 10^9 + 7 取餘後返回。
    示例 1:
    輸入:arr = [1,3,5]
    輸出:4
    解釋:所有的子陣列為 [[1],[1,3],[1,3,5],[3],[3,5],[5]] 。
    所有子陣列的和為 [1,4,9,3,8,5].
    奇數和包括 [1,9,3,5] ,所以答案為 4 。
    示例 2 :
    輸入:arr = [2,4,6]
    輸出:0
    解釋:所有子陣列為 [[2],[2,4],[2,4,6],[4],[4,6],[6]] 。
    所有子陣列和為 [2,6,12,4,10,6] 。
    所有子陣列和都是偶數,所以答案為 0 。
    示例 3:
    輸入:arr = [1,2,3,4,5,6,7]
    輸出:16
    示例 4:
    輸入:arr = [100,100,99,99]
    輸出:4
    示例 5:
    輸入:arr = [7]
    輸出:1

老套路了,記錄字首和奇數和偶數的個數
計算包含當前元素時的答案個數

int mod = 1e9+7;
class Solution {
public:
    int numOfSubarrays(vector<int>& arr) {
        //prefixsum and cal the number of odd and even number before it
        for(int i=1; i<arr.size(); i++)
            arr[i] += arr[i-1];
        int ans = 0;
        int a[]={0,0};
        for(int i=0; i<arr.size(); i++){
            a[arr[i]&1]++;
            if(arr[i]&1){
                ans = (ans+a[0]+1)%mod;
            }else
                ans = (ans+a[1])%mod;
        }
        return ans;
    }
};

字首一次求不同的字母個數
從後面迴圈求解

class Solution {
public:
    int numSplits(string s) {
        vector<int> cnt(s.length());
        int occur[26];
        memset(occur, 0, sizeof occur);
        int num=0;
        for(int i=0; i<s.length(); i++){
            if(!occur[s[i]-'a']){
                occur[s[i]-'a']=1;
                num++;
            }
            cnt[i]=num;
        }
        num=0;
        int ans=0;
        memset(occur, 0, sizeof occur);
        for(int i=s.length()-1; i>0; i--){
            if(!occur[s[i]-'a']){
                occur[s[i]-'a']=1;
                num++;
            }
            if(num==cnt[i-1]) ans++;
            if(num>cnt[i-1]) break;
        }
        return ans;
    }
};

直覺告訴我們,如果當前元素比後一個元素小
那麼: 對當前元素進行增加的同時而不對後一個增加的話結果肯定不是最優的
而如果當前元素比後一個元素大,那麼肯定前面大的那個尖的塔要被消去
所以只需要順序掃描一次,每當後一個比當前小,就累加差距,為了方便在陣列後面加一個0

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