真正写对「二分查找」,从来不在于我们把区间写成了「左闭右开」还是「左闭右闭」,而是 在于我们能够根据题意:得到某种单调性,和可以逐步缩小搜索规模的条件,进而准确地设计可以使得搜索区间缩小的条件。
150题纪念:
745. 前缀和后缀搜索(148)
代码实现(部分看题解)
class WordFilter {
public:
map<string, int> dict;
WordFilter(vector<string>& words) {
int n = words.size();
for (int i = 0; i < n; i++) {
int m = words[i].size();
for (int pref = 1; pref <= m; pref++) {
for (int suff = 1; suff <= m; suff++) {
string key = words[i].substr(0, pref) + '#' +
words[i].substr(m - suff);
// cout << key << endl;
dict[key] = i;
}
}
}
}
int f(string pref, string suff) {
string target = pref + '#' + suff;
return dict.count(target) ? dict[target] : -1;
}
};
/**
* Your WordFilter object will be instantiated and called as such:
* WordFilter* obj = new WordFilter(words);
* int param_1 = obj->f(pref,suff);
*/
1482. 制作 m 束花所需的最少天数(149)
代码实现(首刷自解)
class Solution {
public:
int minDays(vector<int>& bloomDay, int m, int k) {
int n = bloomDay.size();
if (m * k > n) return -1;
int l = *min_element(bloomDay.begin(), bloomDay.end()),
r = *max_element(bloomDay.begin(), bloomDay.end());
while (l < r) {
int mid = l + (r - l) / 2;
int count = 0;
for (int i = 0; i < n; i++) {
if (i + k - 1 >= n) break;
bool flag = true;
int j;
for (j = i; j < i + k; j++) {
if (mid < bloomDay[j]) {
flag = false;
break;
}
}
if (flag) {
count++;
i = j - 1;
}
else i = j;
}
if (count >= m) r = mid;
else l = mid + 1;
}
return l;
}
};
1818. 绝对差值和(150)
代码实现(首刷自解)
class Solution {
public:
int minAbsoluteSumDiff(vector<int>& nums1, vector<int>& nums2) {
int n = nums1.size();
long long sums = 0;
for (int i = 0; i < n; i++) {
sums += abs(nums2[i] - nums1[i]);
}
if (sums == 0 || n == 1) return 0;
vector<int> sortedNums1 = nums1;
sort(sortedNums1.begin(), sortedNums1.end());
long long ans = sums;
for (int i = 0; i < n; i++) {
// find the best element to replace
if (nums2[i] >= sortedNums1.back()) {
ans = min(ans, sums - abs(nums2[i] - nums1[i])
+ abs(nums2[i] - sortedNums1.back()));
continue;
}
int l = 0, r = n - 1;
while (l < r) {
int m = (l + r) >> 1;
if (sortedNums1[m] >= nums2[i]) r = m;
else l = m + 1;
}
int replace;
if (l == 0) {
replace = min(abs(nums2[i] - sortedNums1[0]),
abs(nums2[i] - sortedNums1[1]));
}
else {
replace = min(abs(nums2[i] - sortedNums1[l - 1]),
abs(nums2[i] - sortedNums1[l]));
}
ans = min(ans, sums - abs(nums2[i] - nums1[i])
+ replace);
}
return ans % 1000000007;
}
};