// 普通二分算法,查找target目标值 while (l < r) { int mid = (l + r) >> 1; if (nums[mid] < target) { l = mid + 1; } else if (nums[mid] > target) { r = mid - 1; } else { // nums[mid] == target return mid; } } return -1; // 没有找到 // 查找第一个大于等于target值的下标 while (l < r) { int mid = (l + r) >> 1; if (nums[mid] >= target) { r = mid; // r为最终结果 } else { l = mid + 1; } } // 查找第一个大于target值的下标 while (l < r) { int mid = (l + r) >> 1; if (nums[mid] > target) { r = mid; // r为最终结果 } else { l = mid + 1; } }
Class UnionSet { public: int *fa, n; UnionSet(int n) : n(n) { fa = new int[n + 1]; for (int i = 0; i <= n; i++) fa[i] = i; } int get(int x){ return fa[x] = (fa[x] == x ? x : get(fa[x]); } void merge(int a, int b) { fa[get[a]] = get(b); } };
用于求RMQ(Range Minimum/Maximum Query)问题——求区间最值的问题
vector<int> maxSlidingWindow(vector<int>& nums, int k) { deque<int> q; vector<int> ret; for (int i = 0; i < nums.size(); i++) { while (q.size() && nums[q.back()] < nums[i]) { q.pop_back(); } q.push_back(i); if (i - q.front() == k) { q.pop_front(); } if (i + 1 < k) { continue; } ret.push_back(nums[q.front()]); } return ret; }
找到下一个更大/更小的元素
vector<int> nextGreatElement(vector<int> & num1, vector<int> & nums2) { vector<int> ret(nums.size()); stack<int> s; for (int i = 0; i < nums.size(); i++) { while(s.size() && nums[s.top()] < nums[i]]) { ret[s.top()] = nums[i]; s.pop(); } s.push(i); } return ret; }
void slidingWindow(string s, string t) { unordered_map<char, int> h, window; for (char c : t) { h[c]++; } int l = 0; int r = 0; int valid = 0; while (right < s.size()) { char c = s[r]; r++; ... // 进行窗口内数据的一系列更新 while (window needs shrink) { char d == s[l++]; l++; ... // 进行窗口内数据的一系列更新 } } }
差分数组对应的概念是前缀和数组,对于数组 [1,2,2,4],其差分数组为 [1,1,0,2],差分数组的第 i 个数即为原数组的第 i-1 个元素和第 i 个元素的差值,也就是说我们对差分数组求前缀和即可得到原数组。
差分数组的性质是,当我们希望对原数组的某一个区间[l,r]施加一个增量inc时,差分数组 d 对应的改变是:d[l] 增加 inc ,d[r+1] 减少 inc。这样对于区间的修改就变为了对于两个位置的修改。并且这种修改是可以叠加的,即当我们多次对原数组的不同区间施加不同的增量,我们只要按规则修改差分数组即可。
未完待续