classSolution { public: intpathSum(vector<int>& nums){ unordered_map<int, int> t; for (int x : nums) { t[x / 10] = x % 10; // 利用现有父子关系 } dfs(t, 11, 0); return res; }
voiddfs(unordered_map<int, int> &t, int i, int s){ if (!t.count(i)) return; s += t[i]; int r = i + 10 + i % 10, l = r - 1; // 33->45和46即33->43然后43+3得到46再-1得到45 if (!t.count(l) && !t.count(r)) { res += s; return; } dfs(t, l, s); dfs(t, r, s); }
classAllOne { public: /** Initialize your data structure here. */ AllOne() {
}
/** Inserts a new key <Key> with value 1. Or increments an existing key by 1. */ voidinc(string key){ if (key2bucket.count(key) == 0) { key2bucket[key] = buckets.insert(buckets.end(), {0, {key}}); // 找不到『旧bucket』就先插一个 } auto curr = key2bucket[key], prev = std::prev(curr); if (curr == buckets.begin() || prev->value > curr->value + 1) { prev = buckets.insert(curr, {curr->value + 1, {}}); // 如果没有『新bucket』就插一个 } prev->keys.insert(key); // 从旧bucket挪到新bucket curr->keys.erase(key); if (curr->keys.empty()) { buckets.erase(curr); } key2bucket[key] = prev; }
/** Decrements an existing key by 1. If Key's value is 1, remove it from the data structure. */ voiddec(string key){ if (key2bucket.count(key) == 0) return; auto curr = key2bucket[key], next = std::next(curr); key2bucket.erase(key); // 先删key反正后边要不删了就删了要不写新key if (curr->value != 1) { if (next == buckets.end() || curr->value - 1 > next->value) { next = buckets.insert(next, {curr->value - 1, {}}); // 如果没有『新bucket』加一个 } next->keys.insert(key); // 从旧bucket挪到新bucket key2bucket[key] = next; } curr->keys.erase(key); if (curr->keys.empty()) { buckets.erase(curr); } }
/** Returns one of the keys with maximal value. */ stringgetMaxKey(){ return buckets.empty() ? "" : *begin(buckets.front().keys); }
/** Returns one of the keys with Minimal value. */ stringgetMinKey(){ return buckets.empty() ? "" : *begin(buckets.back().keys); }
structBucket { int value = 0; unordered_set<string> keys; }; unordered_map<string, list<Bucket>::iterator> key2bucket; list<Bucket> buckets; };
/** * Your AllOne object will be instantiated and called as such: * AllOne obj = new AllOne(); * obj.inc(key); * obj.dec(key); * string param_3 = obj.getMaxKey(); * string param_4 = obj.getMinKey(); */
classSolution { public: boolcanCross(vector<int>& stones){ for (int i = 0, limit = 0; i < stones.size(); ++i) { // 可有可无,只是一个优化,假设前面每一跳都比前面一跳加1,那么到第i跳之后应该到 i * (i + 1) / 2,假如stones[i]比这个要远,则意味着永远到不了stones[i] limit += i; if (stones[i] > limit) returnfalse; } return canCross(stones, 0, 0); }
boolcanCross(constvector<int> &stones, int b, int k){ // 上一步步长为k达到的stones[b],从b + 1开始遍历看[k - 1, k + 1]步长之内能到哪些stones int n = stones.size(); if (b == n - 1) returntrue; auto key = (k << 11) | b; // 如果是全部integer则要用long key = (k << 32) | b; if (m.count(key)) return m[key]; for (int i = b + 1; i < n; ++i) { // 这个循环实际上只需要遍历最多三个stones int jump = stones[i] - stones[b]; if (jump < k - 1) continue; if (jump > k + 1) break; if (canCross(stones, i, jump)) return m[key] = true; } return m[key] = false; }
unordered_map<int, bool> m; // 每个石头的下标+尝试到达stones[i]所需要的步长 和 用这个步长是否能到达stones[i] };
classSolution { public: boolcanCross(vector<int>& stones){ n = stones.size(); for (int i = 0; i < n; ++i) { dict[stones[i]] = i; } return canCross(stones, 0, 1); }
boolcanCross(constvector<int> &stones, int b, int k){ if (k <= 0) returnfalse; if (b == n - 1) returntrue; auto key = (k << 11) | b; if (m.count(key)) return m[key]; int next = stones[b] + k; if (dict.count(next) == 0) returnfalse; for (int d = -1; d <= 1; ++d) { if (canCross(stones, dict[next], k + d)) return m[key] = true; } return m[key] = false; }
classSolution { public: boolcanCross(vector<int>& stones){ unordered_map<int, unordered_set<int>> m; // 每个石头的位置stones[i]和到stones[i]有可能的步长 for (int s : stones) { m[s] = {}; // 这一步必须要有,否则无法判断是否存在指定位置的石头 } m[stones[0]].insert(0); for (int s : stones) { for (int k : m[s]) { // 每个石头最多只可能继承n种步长(否则就到最后一个了)所以内循环复杂度上限是O(n) for (int d = -1; d <= 1; ++d) { int t = s + k + d; if (t == stones.back()) returntrue; if (k + d > 0 && m.count(t)) { m[t].insert(k + d); } } } } returnfalse; } };
classSolution { public: vector<int> smallestRange(vector<vector<int>>& nums){ multimap<int, int, greater<int>> m; int k = nums.size(); for (int i = 0; i < k; ++i) { m.emplace(nums[i].back(), i); nums[i].pop_back(); } vector<int> res{-100000, 100000}; while (!m.empty()) { auto h = begin(m); auto l = rbegin(m); auto [hi, i] = *h; auto [lo, _] = *l; if (hi - lo <= res[1] - res[0]) { res = {lo, hi}; } m.erase(h); if (nums[i].empty()) break; m.emplace(nums[i].back(), i); nums[i].pop_back(); } return res; } };
max heap O(nlogk) n是数的个数,k是数组个数,这里用最大堆是想让每个数组从后往前剔除元素,避免维护指针麻烦 题目解法和merge k sorted lists类似,上来先取每个数组的最大值放入堆,并维护一个全局最小值,然后不停从堆顶元素对应的数组取数并更新堆顶、全局最小值和最大值直到某个数组为空
classSolution { public: vector<int> smallestRange(vector<vector<int>>& nums){ using pii = pair<int, int>; priority_queue<pii, vector<pii>> q; int k = nums.size(); int lo = INT_MAX, hi = INT_MIN; for (int i = 0; i < k; ++i) { lo = min(lo, nums[i].back()); hi = max(hi, nums[i].back()); q.emplace(nums[i].back(), i); nums[i].pop_back(); } vector<int> res{lo, hi}; while (!q.empty()) { auto [hi, i] = q.top(); q.pop(); if (hi - lo <= res[1] - res[0]) { // 因为是有序的,所以不需要单独考虑差系统的情况,但是必须要用小于等于,因为是从大到小遍历的,所以后边有可能有差相同但是range开端更小的来overwrite结果 res = {lo, hi}; } if (nums[i].empty()) break; lo = min(lo, nums[i].back()); q.emplace(nums[i].back(), i); nums[i].pop_back(); } return res; } };
greedy+sliding window O(nlogn + n) time O(n) space 题解