classSolution { public: vector<int> mostCompetitive(vector<int>& nums, int k){ using pii = pair<int, int>; auto cmp = [](pii a, pii b) -> bool { if (a.first != b.first) { return a.first > b.first; } else { return a.second > b.second; } }; priority_queue<pii, vector<pii>, decltype(cmp)> m(cmp); for (int i = 0; i + k - 1 < nums.size(); ++i) { m.push({nums[i], i}); } int begin = 0; vector<int> ans; while (k > 0) { auto p = m.top(); m.pop(); while (p.second < begin && !m.empty()) { p = m.top(); m.pop(); } begin = p.second; ans.push_back(p.first); --k; if (k == 0) break; m.push({nums[nums.size() - k], nums.size() - k}); } return ans; } };
Time complexity: O(N log N), space complexity: O(N).
1674. Minimum Moves to Make Array Complementary
I recorded my contest-time thinking in the comments. Finally, inspiration struck: determine the range where each pair needs one change, then enumerate every possible target sum and quickly compute the number of changes needed in O(log N).
classSolution { staticconstint MAX = 1e5 + 5; int open[MAX], close[MAX], dot[MAX]; public: intminMoves(vector<int>& nums, int limit){ // 统计和的最大众数,变其他。但是有的需要大于limit (x) // 二分,快速求判定问题? // 暴力,枚举互补数,遍历一遍再。O(n * n) // a + b = 互补数,0 // a + b 变 互补数: 1, 2 // 0次变 是一个数 // 一次变最大,一次变最小 是一个范围 // 出了范围就需要2次变 // 确定互补数,可以遍历一遍确定变数 // 确定变数呢? // | . | // open - close: in range // close + total - open: out range // dtop: 0 constint n = nums.size(); for (int i = 0; i < n - 1 - i; ++i) { int a = nums[i]; int b = nums[n - 1 - i]; if (a > b) swap(a, b); // a <= b int lower = a + 1; int upper = b + limit; dot[i] = a + b; open[i] = lower; close[i] = upper; } constint size = n / 2; auto openEnd = begin(open) + size; auto closeEnd = begin(close) + size; auto dotEnd = begin(dot) + size; sort(begin(open), openEnd); sort(begin(close), closeEnd); sort(begin(dot), dotEnd); auto need = [&](constint line) -> int { auto itOpen = upper_bound(begin(open), openEnd, line); auto itClose = lower_bound(begin(close), closeEnd, line); auto itDot = lower_bound(begin(dot), dotEnd, line); auto itDot2 = upper_bound(itDot, dotEnd, line); int dotNumber = distance(itDot, itDot2); int outRange = 0; outRange += distance(begin(close), itClose); outRange += distance(itOpen, openEnd); int inRange = n / 2 - dotNumber - outRange; return inRange + 2 * outRange; }; int ans = n; for (int line = 2; line <= limit * 2; ++line) { constint condidate = need(line); // cout << line << ": " << condidate << endl; ans = min(ans, condidate); } return ans; } };
Time complexity: O(limit * log N), space complexity: O(N).
During the contest, C++ was hit by constant-factor limits. I had to change arrays to global arrays to AC. I am usually more accustomed to using local vector, which is more readable and maintainable.
Using a difference array can avoid binary search. See zerotrac’s solution for details. This was also my first time encountering the concept of a difference array.