2021-04-17 Daily-Challenge

Today is Saturday, I gonna review the tasks I've done this week, and finish today's leetcode's April LeetCoding Challenge with cpp.

LeetCode Review

Beautiful Arrangement II

too easy to review

Flatten Nested List Iterator

already done a good work

Partition List

too easy to review

Fibonacci Number

already done a good work

Remove All Adjacent Duplicates in String II

too easy to review

Implement Trie (Prefix Tree)

too easy to review

Reverse Linked List

too easy to review

Average Salary Excluding the Minimum and Maximum Salary

too easy to review

LFU Cache

cpp got not LinkedHashSet, so I fail to implement a $O(1)$ solution this time.

class LFUCache {
  int capacity;
  unordered_map<int, int> kv;
  unordered_map<int, int> cntKV;
  unordered_map<int, int> freq;
  unordered_map<int, set<pair<int, int>>> freqKey;
  int min = INT_MAX;
  int size = 0;
  int cnt = 0;
public:
  LFUCache(int c): capacity(c) { }

  int get(int key) {
    if(!kv.count(key)) return -1;
    int f = freq[key];
    freqKey[f].erase(make_pair(cntKV[key], key));
    if(freqKey[f].empty()) {
      freqKey.erase(f);
      if(f == min) min = f + 1;
    }
    freqKey[f + 1].emplace(make_pair(++cnt, key));
    cntKV[key] = cnt;
    freq[key] = f + 1;
    return kv[key];
  }

  void put(int key, int value) {
    if(!capacity) return;
    if(kv.count(key)) {
      int f = freq[key];
      freqKey[f].erase(make_pair(cntKV[key], key));
      if(freqKey[f].empty()) {
        freqKey.erase(f);
        if(f == min) min = f + 1;
      }
      freqKey[f + 1].emplace(make_pair(++cnt, key));
      freq[key] = f + 1;
    } else {
      if(size == capacity) {
        size -= 1;
        int removedKey = freqKey[min].begin()->second;
        kv.erase(removedKey);
        freqKey[min].erase(freqKey[min].begin());
        if(freqKey[min].empty() && min != 1) freqKey.erase(min);
      }
      size += 1;
      freqKey[1].emplace(make_pair(++cnt, key));
      freq[key] = 1;
      min = 1;
    }

    cntKV[key] = cnt;
    kv[key] = value;
  }
};

Find a Value of a Mysterious Function Closest to Target

I finally optimize it by quick return!

constexpr int maxBit(int x) {
  for(int i = 30; i >= 0 ; --i){
    if((1 << i) & x) return (1 << i);
  }
  return -1;
}
class Solution {
  int len;
  int closestToOneBit(vector<int>& arr, int bit, int target) {
    int pos = 0;
    int result = INT_MAX;
    while(pos < len) {
      if(!(arr[pos] & bit)) {
        pos += 1;
      } else {
        int res = arr[pos];
        while(pos < len && (arr[pos] & bit)) {
          res &= arr[pos];
          pos += 1;
        }
        result = min(result, abs(res - target));
      }
    }
    return result;
  }
public:
  int closestToTarget(vector<int>& arr, int target) {
    int all = (1 << 26) - 1;
    len = arr.size();
    int mmax = 0;
    for(auto n : arr) {
      mmax = max(n, mmax);
      all &= n;
    }
    if(mmax <= target) return target - mmax;
    if(all >= target) return all - target;
    int mBit = (maxBit(target) << 1);
    int bit = mBit;
    int answer = INT_MAX;
    while(bit) {
      answer = min(answer, closestToOneBit(arr, bit, target));
      if(answer != INT_MAX && (mBit >> 2) > bit) return answer;
      bit >>= 1;
    }
    return answer;
  }
};

// Runtime: 88 ms, faster than 95.69% of C++ online submissions for Find a Value of a Mysterious Function Closest to Target.
// Memory Usage: 62.5 MB, less than 88.79% of C++ online submissions for Find a Value of a Mysterious Function Closest to Target.

April LeetCoding Challenge 17

Description

Number of Submatrices That Sum to Target

Given a matrix and a target, return the number of non-empty submatrices that sum to target.

A submatrix x1, y1, x2, y2 is the set of all cells matrix[x][y] with x1 <= x <= x2 and y1 <= y <= y2.

Two submatrices (x1, y1, x2, y2) and (x1', y1', x2', y2') are different if they have some coordinate that is different: for example, if x1 != x1'.

Example 1:

img

Input: matrix = [[0,1,0],[1,1,1],[0,1,0]], target = 0
Output: 4
Explanation: The four 1x1 submatrices that only contain 0.

Example 2:

Input: matrix = [[1,-1],[-1,1]], target = 0
Output: 5
Explanation: The two 1x2 submatrices, plus the two 2x1 submatrices, plus the 2x2 submatrix.

Example 3:

Input: matrix = [[904]], target = 0
Output: 0

Constraints:

  • 1 <= matrix.length <= 100
  • 1 <= matrix[0].length <= 100
  • -1000 <= matrix[i] <= 1000
  • -10^8 <= target <= 10^8

Solution

class Solution {
public:
  int numSubmatrixSumTarget(vector<vector<int>>& matrix, int target) {
    int rows = matrix.size();
    int cols = matrix.front().size();
    vector<vector<int>> sum(rows + 1, vector<int>(cols + 1));
    for(int i = 0; i < rows; ++i) {
      for(int j = 0; j < cols; ++j) {
        sum[i + 1][j + 1] = sum[i + 1][j] + sum[i][j + 1] - sum[i][j] + matrix[i][j];
      }
    }
    int answer = 0;
    for(int i = 0; i < cols; ++i) {
      for(int j = i + 1; j <= cols; ++j) {
        multiset<int> tmp{0};
        for(int row = 1; row <= rows; ++row) {
          int curSum = sum[row][j] - sum[row][i];
          answer += tmp.count(curSum - target);
          tmp.insert(curSum);
        }
      }
    }
    return answer;
  }
};

// 40 / 40 test cases passed.
// Status: Accepted
// Runtime: 572 ms
// Memory Usage: 166 MB

using map is slower, maybe due to insertion and initialization?

class Solution {
public:
  int numSubmatrixSumTarget(vector<vector<int>>& matrix, int target) {
    int rows = matrix.size();
    int cols = matrix.front().size();
    vector<vector<int>> sum(rows + 1, vector<int>(cols + 1));
    for(int i = 0; i < rows; ++i) {
      for(int j = 0; j < cols; ++j) {
        sum[i + 1][j + 1] = sum[i + 1][j] + sum[i][j + 1] - sum[i][j] + matrix[i][j];
      }
    }
    int answer = 0;
    for(int i = 0; i < cols; ++i) {
      for(int j = i + 1; j <= cols; ++j) {
        map<int, int> tmp{{0, 1}};
        for(int row = 1; row <= rows; ++row) {
          int curSum = sum[row][j] - sum[row][i];
          answer += tmp[curSum - target];
          tmp[curSum] += 1;
        }
      }
    }
    return answer;
  }
};

// 40 / 40 test cases passed.
// Status: Accepted
// Runtime: 972 ms
// Memory Usage: 274.8 MB

yes

class Solution {
public:
  int numSubmatrixSumTarget(vector<vector<int>>& matrix, int target) {
    int rows = matrix.size();
    int cols = matrix.front().size();
    vector<vector<int>> sum(rows + 1, vector<int>(cols + 1));
    for(int i = 0; i < rows; ++i) {
      for(int j = 0; j < cols; ++j) {
        sum[i + 1][j + 1] = sum[i + 1][j] + sum[i][j + 1] - sum[i][j] + matrix[i][j];
      }
    }
    int answer = 0;
    for(int i = 0; i < cols; ++i) {
      for(int j = i + 1; j <= cols; ++j) {
        map<int, int> tmp{{0, 1}};
        for(int row = 1; row <= rows; ++row) {
          int curSum = sum[row][j] - sum[row][i];
          answer += tmp.count(curSum - target) ? tmp[curSum - target] : 0;
          tmp[curSum] += 1;
        }
      }
    }
    return answer;
  }
};


// 40 / 40 test cases passed.
// Status: Accepted
// Runtime: 648 ms
// Memory Usage: 164.9 MB

unordered_set is similar

class Solution {
public:
  int numSubmatrixSumTarget(vector<vector<int>>& matrix, int target) {
    int rows = matrix.size();
    int cols = matrix.front().size();
    vector<vector<int>> sum(rows + 1, vector<int>(cols + 1));
    for(int i = 0; i < rows; ++i) {
      for(int j = 0; j < cols; ++j) {
        sum[i + 1][j + 1] = sum[i + 1][j] + sum[i][j + 1] - sum[i][j] + matrix[i][j];
      }
    }
    int answer = 0;
    for(int i = 0; i < cols; ++i) {
      for(int j = i + 1; j <= cols; ++j) {
        unordered_map<int, int> tmp{{0, 1}};
        for(int row = 1; row <= rows; ++row) {
          int curSum = sum[row][j] - sum[row][i];
          answer += tmp.count(curSum - target) ? tmp[curSum - target] : 0;
          tmp[curSum] += 1;
        }
      }
    }
    return answer;
  }
};

// 40 / 40 test cases passed.
// Status: Accepted
// Runtime: 612 ms
// Memory Usage: 174 MB

optimization with principle of locality seems useless

class Solution {
public:
  int numSubmatrixSumTarget(vector<vector<int>>& matrix, int target) {
    int rows = matrix.size();
    int cols = matrix.front().size();
    vector<vector<int>> rowPrefix(rows, vector<int>(cols + 1));
    for(int i = 0; i < rows; ++i) {
      for(int j = 0; j < cols; ++j) {
        rowPrefix[i][j + 1] = rowPrefix[i][j] + matrix[i][j];
      }
    }
    int answer = 0;
    for(int i = 0; i < cols; ++i) {
      for(int j = i + 1; j <= cols; ++j) {
        int sum = 0;
        multiset<int> tmp{0};
        for(int row = 0; row < rows; ++row) {
          sum += rowPrefix[row][j] - rowPrefix[row][i];
          answer += tmp.count(sum - target);
          tmp.insert(sum);
        }
      }
    }
    return answer;
  }
};

// 40 / 40 test cases passed.
// Status: Accepted
// Runtime: 596 ms
// Memory Usage: 166 MB