intminEatingSpeed(vector<int>& piles, int h){ int left = 1, right = 1000000001; // 寻找最小速度,找左边界 while (left < right) { int mid = left + (right - left) / 2; if (f(piles, mid, h)) { right = mid; } else { left = mid + 1; } } return left; }
// 定义:速度为 x 时,需要 f(x) 小时吃完所有香蕉 // 判断当前速度能否在h小时内完成 intf(vector<int>& piles, int x, int h){ int hours = 0; for (int i = 0; i < piles.size(); i++) { hours += piles[i] / x; if (piles[i] % x > 0) { hours++; } } return hours <= h; }
intkthSmallest(vector<vector<int>>& matrix, int k){ int n = matrix.size(); int left = matrix[0][0]; int right = matrix[n-1][n-1]; // 寻找左边界 while (left < right) { int mid = left + (right - mid) / 2; if (check(matrix, k, mid)) { right = mid; } else { left = mid + 1; } } return left; } // 判断不大于mid的总数,是否大于k; boolcheck(vector<vector<int>>& matrix, int k, int mid){ int n = matrix.size(); int count = 0; int tmp = n - 1; for (int i = 0; i < n; i++) { while (tmp >= 0 && matrix[tmp][i] > mid) { tmp--; } count += (tmp + 1); } return count >= k; }
传送带上的包裹必须在 days 天内从一个港口运送到另一个港口。 传送带上的第 i 个包裹的重量为 weights[i]。每一天,我们都会按给出重量(weights)的顺序往传送带上装载包裹。我们装载的重量不会超过船的最大运载重量。 返回能在 days 天内将传送带上的所有包裹送达的船的最低运载能力。
intshipWithinDays(vector<int>& weights, int days){ int left = 0, right = 1; for (auto& w : weights) { left = max(left, w); right += w; }
while (left < right) { int mid = left + (right - left) / 2; if (getDays(weights, mid) <= days) { right = mid; } else { left = mid + 1; } } return left; }
intgetDays(vector<int>& weights, int x){ int days = 0; for (int i = 0; i < weights.size();) { int cap = x; while (i < weights.size()) { if (cap < weights[i]) break; else { cap -= weights[i++]; } } days++; } return days; }
intsplitArray(vector<int>& nums, int m){ int n = nums.size(), left = 0, right = 1; for (auto& a : nums) { left = max(left, a); right += a; } while (left < right) { int mid = left + (right - left) / 2; int count = 0; for (int i = 0; i < n;) { int sum = mid; while (i < n) { if (nums[i] > sum) { break; } else { sum -= nums[i++]; } } count++; } if (count <= m) { right = mid; } else { left = mid + 1; } } return left; }
假定最小磁力为ans,小于ans的答案也一定合法。既然我们存在一种放置的方法使得相邻小球间距的最小值大于等于 ans,那么也一定大于 [1,ans−1] 中的任意一个值,而大于 ans 的均不合法,因此我们可以对答案进行二分查找。在区间[left, right]之间查找,每次取mid为平均值:
如果当前mid合法,令ans = mid,并将区间缩小为[mid + 1, right];
如果当前mid不合法,则将区间缩小为[left, mid - 1].
预先对给定的篮子的位置进行排序,那么从贪心的角度考虑,第一个小球放置的篮子一定是 position 最小的篮子,即排序后的第一个篮子。那么为了满足上述条件,第二个小球放置的位置一定要大于等于 position[0]+x,接下来同理。因此我们从前往后扫 position 数组,看在当前答案 x 下我们最多能在篮子里放多少个小球,我们记这个数量为 cnt,如果 cnt 大于等于 m,那么说明当前答案下我们的贪心策略能放下 m 个小球且它们间距均大于等于 x ,为合法的答案,否则不合法。
intmaxDistance(vector<int>& position, int m){ sort(position.begin(), position.end()); int n = position.size(); int left = 1, right = position[n-1] - position[0]; int ans = -1; // 寻找满足成立条件的右边界 while (left <= right) { int mid = left + (right - left) / 2; if (check(position, mid, m)) { ans = mid; left = mid + 1; } else { right = mid - 1; } } return ans; } // 检查以x为最小磁力,得到的分组cnt是否大于等于m boolcheck(vector<int>& position, int x, int m){ int pre = position[0], cnt = 1; for (int i = 1; i < position.size(); i++) { if (position[i] - pre >= x) { cnt++; pre = position[i]; } } return cnt >= m; }
intminTime(vector<int>& time, int m){ int n = time.size(); int left = 0, right = 1; for (auto& t : time) { right += t; } while (left < right) { int mid = left + (right - left) / 2; if (getDays(time, mid) <= m) { right = mid; } else { left = mid + 1; } } return left; }
intgetDays(vector<int>& time, int x){ int useday = 1, totaltime = 0, maxtime = 0; for (int i = 0; i < time.size(); i++) { int nextime = min(maxtime, time[i]); if (nextime + totaltime <= x) { totaltime += nextime; maxtime = max(maxtime, time[i]); } else { useday++; totaltime = 0; maxtime = time[i]; } } return useday; }
差分数组:第i个数即为原数组第i-1个元素和第i个元素的差值,也就是说对差分数组求前缀和即可得到原始数组。 遍历给定的预定数组,对差分数据进行更新,完成修改。对于预定记录booking=[l,r,inc],我们需要让d[l−1] 增加 inc,d[r] 减少inc。特别地,当 r 为 n 时,我们无需修改d[r],因为这个位置溢出了下标范围。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
vector<int> corpFlightBookings(vector<vector<int>>& bookings, int n){ vector<int> res(n, 0); for (int i = 0; i < bookings.size(); i++) { int first = bookings[i][0] - 1; int last = bookings[i][1]; res[first] += bookings[i][2]; if (last < n) { res[last] -= bookings[i][2]; } } for (int i = 1; i < n; i++) { res[i] += res[i-1]; } return res; }
intmaxSumRangeQuery(vector<int>& nums, vector<vector<int>>& requests){ int n = nums.size(); vector<int> count(n, 0); for (auto& req : requests) { int first = req[0]; int last = req[1]; count[first]++; if (last + 1 < n) count[last+1]--; } for (int i = 1; i < n; i++) { count[i] += count[i-1]; } sort(nums.begin(), nums.end()); sort(count.begin(), count.end()); longlong sum = 0; int Mod = 1000000007; for (int i = n - 1; i >= 0 && count[i] > 0; i--) { sum += (longlong) nums[i] * count[i]; } return (int)(sum % Mod); }
boolcarPooling(vector<vector<int>>& trips, int capacity){ vector<int> res(1001, 0); for (auto& trip : trips) { int first = trip[1]; int last = trip[2]; res[first] += trip[0]; res[last] -= trip[0]; } for (int i = 0; i < res.size(); i++) { if (i > 0) res[i] += res[i-1]; if (res[i] > capacity) { returnfalse; } } returntrue; }
voidUnion(vector<int>& parent, int index1, int index2){ // 建立连通性 parent[Find(parent, index1)] = Find(parent, index2); }
intfindCircleNum(vector<vector<int>>& isConnected){ int cities = isConnected.size(); vector<int> parent(cities, 0); for (int i = 0; i < cities; i++) { parent[i] = i; } for (int i = 0; i < cities; i++) { for (int j = i+1; j < cities; j++) { if (isConnected[i][j] == 1) { Union(parent, i, j); } } } int provinces = 0; for (int i = 0; i < cities; i++) { if (parent[i] == i) { provinces++; } } return provinces; }
voidUnion(vector<int>& parent, int index1, int index2){ // 建立连通性 parent[Find(parent, index1)] = Find(parent, index2); } intminimumHammingDistance(vector<int>& source, vector<int>& target, vector<vector<int>>& allowedSwaps){ int n = source.size(); vector<int> parent(n, 0); for (int i = 0; i < n; i++) { parent[i] = i; } for (constauto& allowed : allowedSwaps) { Union(parent, allowed[0], allowed[1]); }
unordered_map<int, unordered_multiset<int>> s, t; // 为每个联通分支维护位置的集合 for (int i = 0; i < n; i++) { int fa = Find(parent, i); s[fa].insert(source[i]); //t[fa].insert(target[i]); }
int res = 0; for (int i = 0; i < n; i++) { auto& m = s[Find(parent, i)]; // 如果通过下标找到的连通块中,有target[i]这个元素,那么将其删掉,反之res++ auto t = m.find(target[i]); // 不能使用 m.erase(x),不然会删掉所有的x,应该先定位到其具体位置,再删除 //(因为该元素已经被用来对应了,后续无法再使用,所以要删除) if (t != m.end()) { m.erase(t); } else { res++; }
boolcheckInclusion(string s1, string s2){ int n = s1.size(), m = s2.size(); if (n > m) returnfalse; vector<int> count(26, 0); for (constauto& c : s1) { count[c-'a']++; } int left = 0, right = 0; while (right < s2.size()) { int x = (s2[right] - 'a'); right++; count[x]--; while (count[x] < 0) { count[s2[left] - 'a']++; left++; } if (right - left == n) { returntrue; } } returnfalse; }
vector<int> partitionLabels(string s){ vector<int> count(26, 0); for (int i = 0; i < s.size(); i++) { count[s[i]-'a'] = i; } int left = 0, right = 0;
vector<int> res; while (right < s.size()) { right = count[s[right] - 'a']; int index = left + 1; while (index < right) { if (count[s[index]-'a'] > right) { right = count[s[index]-'a']; } index++; } right++; res.push_back(right - left); left = right;
boolcheckSubarraySum(vector<int>& nums, int k){ int n = nums.size(); if (n < 2) { returnfalse; } unordered_map<int, int> map; map[0] = -1; int remain = 0; for (int i = 0; i < n; i++) { remain = (nums[i] + remain) % k; if (map.find(remain) != map.end()) { int index = map[remain]; if (i - index >= 2) { returntrue; } } else { map[remain] = i; } } returnfalse; }
intmaxNonOverlapping(vector<int>& nums, int target){ int n = nums.size(); int res = 0; int i = 0; while (i < n) { unordered_set<int> s{0}; int sum = 0; while (i < n) { sum += nums[i]; if (s.find(sum - target) != s.end()) { res++; break; } else { s.insert(sum); i++; } } i++; } return res; }
intmaxFrequency(vector<int>& nums, int k){ int n = nums.size(); sort(nums.begin(), nums.end()); vector<longlong> sum(n, 0); sum[0] = nums[0]; for (int i = 1; i < n; i++) { sum[i] = sum[i - 1] + nums[i]; } int ans = 0; for (int i = 0; i < n; i++) { int left = 0, right = i, res = -1; while (left <= right) { int mid = left + (right - left) / 2; if (nums[i] * (longlong)(i - mid + 1) - (sum[i] - (mid > 0 ? sum[mid - 1] : 0)) <= k) { res = mid; right = mid - 1; } else { left = mid + 1; } } if (res != -1) ans = max(ans, i - res + 1); } return ans; }
intmaxFrequency(vector<int>& nums, int k){ int n = nums.size(); sort(nums.begin(), nums.end()); longlong sum = 0; int left = 0; int res = 1; for (int right = 1; right < n; right++) { sum += (longlong) (nums[right] - nums[right-1]) * (right - left); while (sum > k) { sum -= nums[right] - nums[left++]; } res = max(res, right - left + 1); } return res; }
vector<int> dirs = {-1, 0, 1, 0, -1}; vector<vector<int>> memo; int m = 0, n = 0; intlongestIncreasingPath(vector<vector<int>>& matrix){ m = matrix.size(); n = matrix[0].size(); if (m == 0 || n == 0) return0; memo = vector<vector<int>>(m, vector<int>(n, -1)); int res = 0; for (int i = 0; i < m; i++) { for (int j = 0; j < n; j++) { res = max(res, dfs(matrix, i, j)); } } return res; }
intdfs(vector<vector<int>>& matrix, int r, int c){ if (memo[r][c] != -1) { return memo[r][c]; }
int maxLen = 1; for (int k = 0; k < 4; k++) { int x = r + dirs[k]; int y = c + dirs[k+1]; if (x < 0 || x >= m || y < 0 || y >= n || matrix[x][y] <= matrix[r][c]) { continue; } int len = dfs(matrix, x, y) + 1; maxLen = max(maxLen, len); } memo[r][c] = maxLen; return maxLen; }
vector<int> dirs {-1, 0, 1, 0, -1}; int m = 0, n = 0; intnumIslands(vector<vector<char>>& grid){ m = grid.size(); n = grid[0].size(); if (m == 0 || n == 0) return0; int res = 0; for (int i = 0; i < m; i++) { for (int j = 0; j < n; j++) { if (grid[i][j] == '1') { res++; dfs(grid, i, j); } } } return res; }
voiddfs(vector<vector<char>>& grid, int r, int c){ grid[r][c] = '0'; for (int k = 0; k < 4; k++) { int x = r + dirs[k], y = c + dirs[k+1]; if (x < 0 || x >= m || y < 0 || y >= n || grid[x][y] == '0') { continue; } dfs(grid, x, y); } }
vector<int> dirs{-1, 0, 1, 0, -1}; vector<vector<bool>> visited; int m = 0, n = 0;
boolexist(vector<vector<char>>& board, string word){ m = board.size(); n = board[0].size(); if (m == 0 || n == 0) returnfalse; bool flag = false; visited = vector<vector<bool>>(m, vector<bool>(n, 0)); for (int i = 0; i < m; i++) { for (int j = 0; j < n; j++) { if (board[i][j] != word[0]) continue; flag = dfs(board, word, i, j, 0); if (flag) { returntrue; } } } returnfalse; } booldfs(vector<vector<char>>& board, string word, int i, int j, int index){ if (board[i][j] != word[index]) { returnfalse; } elseif (index == word.size() - 1) { returntrue; } visited[i][j] = true; bool res = false; for (int k = 0; k < 4; k++) { int x = i + dirs[k]; int y = j + dirs[k+1]; if (x < 0 || x >= m || y < 0 || y >= n) { continue; } if (!visited[x][y]) { bool flag = dfs(board, word, x, y, index + 1); if (flag) { res = true; break; } } } visited[i][j] = false; return res; }
voidslove(string s, vector<string>& ans, int index){ if (index == s.size()) { ans.push_back(s); return; }
if (isalpha(s[index])) { s[index] = toupper(s[index]); slove(s, ans, index + 1); s[index] = tolower(s[index]); slove(s, ans, index + 1); } else { slove(s, ans, index + 1); } }
回溯搜索,序列中包含了重复的数字,要求我们返回不重复的全排列。将这个问题看作有 n 个排列成一行的空格,我们需要从左往右依次填入题目给定的 n 个数,每个数只能使用一次。先对原始数组进行排序,需要一个visited数组记录已经使用过的数,index记录path待填入的位置,如果index==n说明已经填完,找到可行解将path存入res中,递归结束。递归过程中,如果这个数还未使用过,尝试填入继续填下一位置,需要注意的是,数组中存在重复的元素,因此需要先排序,需要保证重复的数字只被填入一次,如果两个相邻的数相同,而且第一个数并未被使用过,则后续相同的数应该跳过循环不填入。
unordered_map<int, int> count; int maxCnt = 0; vector<int> findFrequentTreeSum(TreeNode* root){ vector<int> res; if (root == nullptr) return res; sum(root); for (auto it : count) { if (it.second == maxCnt) { res.push_back(it.first); } } return res; }
intsum(TreeNode* root){ if (root == nullptr) return0; int left = sum(root->left); int right = sum(root->right); int res = left + right + root->val; count[res]++; maxCnt = max(maxCnt, count[res]); return res; }
queue<TreeNode*> q; q.push(root); while (!q.empty()) { int size = q.size(); int maxVal = INT_MIN; for (int i = 0; i < size; i++) { TreeNode* cur = q.front(); q.pop(); maxVal = max(maxVal, cur->val); if (cur->left) q.push(cur->left); if (cur->right) q.push(cur->right); } res.push_back(maxVal); } return res; }
vector<string> watchedVideosByFriends(vector<vector<string>>& watchedVideos, vector<vector<int>>& friends, int id, int level){ int n = friends.size(); vector<bool> used(n, 0); queue<int> q; q.push(id); used[id] = true; // 寻找id的第level级别的好友将其入队 for (int k = 1; k <= level; k++) { int len = q.size(); for (int i = 0; i < len; i++) { int u = q.front(); q.pop(); for (auto v : friends[u]) { if (!used[v]) { q.push(v); used[v] = true; } } } }
unordered_map<string, int> freq; // 哈希表存储队列中出现的电影名字与其出现次数 while (!q.empty()) { int u = q.front(); q.pop(); for (const string& watched : watchedVideos[u]) { freq[watched]++; } }
intgetImportance(vector<Employee*> employees, int id){ unordered_map<int, Employee*> map; for (auto& e : employees) { map[e->id] = e; } returndfs(id, map); }
intdfs(int id, unordered_map<int, Employee*>& map){ Employee* cur = map[id]; int total = cur->importance; for (auto& i : cur->subordinates) { total += dfs(i, map); } return total; }
intgetImportance(vector<Employee*> employees, int id){ unordered_map<int, Employee*> map; for (auto& e : employees) { map[e->id] = e; }
int total = 0; queue<int> q; q.push(id); //total += map[id]->importance; while (!q.empty()) { int cur_id = q.front(); q.pop(); Employee* cur = map[cur_id]; total += cur->importance; for (auto& i : cur->subordinates) { q.push(i); //total += map[i]->importance; } }