Ashamedly, my ranking fell back to 400+. I had half an hour to solve the last problem and kept trying to use a segment tree. Just like Kick Start Round D, I got obsessed with segment trees and crashed. The lesson learned is: do not insist that interval problems must be solved with segment trees. There are often simpler approaches.
1154. Day of the Year
Determine whether it is a leap year, then accumulate the days in previous months.
Time complexity: O(1), Space complexity: O(1).
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
classSolution { boolisLeap(int yy){ return (yy % 4 == 0 && yy % 100 != 0) || yy % 400 == 0; } public: intdayOfYear(string date){ auto yy = stoi(date.substr(0, 4)); auto mm = stoi(date.substr(5, 2)); auto dd = stoi(date.substr(8, 2)); vector<int> days = {0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}; if (isLeap(yy)) { days[2] = 29; } int ans = 0; ans += accumulate(days.cbegin(), days.cbegin() + mm, 0); ans += dd; return ans; } };
1155. Number of Dice Rolls With Target Sum
Stars and bars, a classic combinatorics problem. Since the interval between two bars cannot be greater than the maximum die face value, it cannot be solved directly with a mathematical formula. I used backtracking with memoization, so it can also be considered DP.
Time complexity: O(N ^ 2), Space complexity: O(d * bar).
classSolution { constint mod = 1e9 + 7; int f; map<pair<int, int>, int> memo; // [begin, end), the index of insert bar intbacktracking(int begin, int end, int bar){ if (memo.find({begin, bar}) != memo.end()) { return memo[{begin, bar}]; } if (bar == 0) { if (end - begin + 1 <= f) return1; else return0; } int ans = 0; for (int i = begin; i < end && i - begin + 1 <= f; ++i) { // insert in i ans += backtracking(i + 1, end, bar - 1); ans %= mod; } memo[{begin, bar}] = ans; return ans; } public: intnumRollsToTarget(int d, int f, int target){ this->f = f; int ans = backtracking(0, target - 1, d - 1); return ans; } };
1156. Swap For Longest Repeated Character Substring
One pass, updating the longest length that can be obtained.
We need to observe that the longest length obtained has nothing to do with the character in the middle gap, and only depends on whether there are needed characters before and after it.
classMajorityChecker { unordered_map<int, vector<int>> appear_index; vector<int> arr; public: MajorityChecker(vector<int>& arr) { for (int i = 0; i < arr.size(); ++i) { appear_index[arr[i]].push_back(i); } this->arr = arr; } intquery(int left, int right, int threshold){ std::random_device dev; std::mt19937 rng(dev()); std::uniform_int_distribution<std::mt19937::result_type> dist6(left,right); // distribution in range [left, right] for (int i = 0; i < 20; ++i) { int a = arr[dist6(rng)]; constauto& index = appear_index[a]; auto l = lower_bound(index.cbegin(), index.cend(), left); auto r = upper_bound(index.cbegin(), index.cend(), right); if (r - l >= threshold) { return a; } } return-1; } };
/** * Your MajorityChecker object will be instantiated and called as such: * MajorityChecker* obj = new MajorityChecker(arr); * int param_1 = obj->query(left,right,threshold); */