前言
来自 英雄哪里出来 的一个 免费 集训,每天
5
5
5 点打卡学习算法(我是为了卷吗,主要是想早起 😏),希望能坚持下去。这里用来复盘每天都的打卡题目。
今日份知识点:双指针(二分)
一、题目
题目 | 难度 |
---|---|
2000. 反转单词前缀 | ⭐️ |
917. 仅仅反转字母 | ⭐️ |
475. 供暖器 | ⭐️⭐️⭐️ |
面试题 16.06. 最小差 | ⭐️ |
二、算法思路
1、反转单词前缀
(1)遍历一遍数组,如果字符串中没有目标字符,直接返回;如果存在目标字符,那么下标从 0 0 0 开始到 i i i 结束,依次交换两端的两个字符。
class Solution {
public:
void swap(char* a, char* b) {
char tmp = *a;
*a = *b;
*b = tmp;
}
string reversePrefix(string word, char ch) {
int i, j;
for (i = 0; i < word.size(); ++ i) {
if (word[i] == ch)
break;
}
if (i == word.size())
return word;
j = 0;
while (j < i) {
swap(&word[i--], &word[j++]);
}
return word;
}
};
2、仅仅反转字母
(1)双指针板子题,两个指针一前一后,依次往中间收,如果字符不是字母,则跳过,找到前后两端的两个字母,然后交换。
class Solution {
public:
void swap(char* a, char* b)
{
char tmp = *a;
*a = *b;
*b = tmp;
}
bool isAlp(char c)
{
return c >= 'a' && c <= 'z' || c >= 'A' && c <= 'Z';
}
string reverseOnlyLetters(string s) {
int i = 0, j = s.size() - 1;
while (i < j) {
if (!isAlp(s[i])) {
++i;
continue;
}
if (!isAlp(s[j])) {
-- j;
continue;
}
swap(&s[i++], &s[j--]);
}
return s;
}
};
3、供暖器
(1)二分答案,双指针检查答案的合理性。
(2)
i
i
i 是
h
o
u
s
e
s
houses
houses 的下标,
j
j
j 是
h
e
a
t
e
r
s
heaters
heaters 下标,那么对于每个答案,其合理性判断如下:
· 如果
h
o
u
s
e
s
(
i
)
≥
h
e
a
t
e
r
s
(
j
)
−
r
houses(i)\geq heaters(j)-r
houses(i)≥heaters(j)−r 并且
h
o
u
s
e
s
(
i
)
≤
h
e
a
t
e
r
s
(
j
)
+
r
houses(i)\leq heaters(j)+r
houses(i)≤heaters(j)+r,那么判断是合法的。
· 如果遍历过程中,有合法的情况,那么直接返回 false;如果全部的
h
o
u
s
e
s
houses
houses 都遍历完了,那么该答案
r
r
r 是合法的,返回 true。
class Solution {
public:
int findRadius(vector<int>& houses, vector<int>& heaters) {
sort(houses.begin(), houses.end());
sort(heaters.begin(), heaters.end());
int l = 0, r = 1e9;
while (l < r) {
int mid = (l + r) >> 1;
if (check(mid, houses, heaters)) r = mid;
else l = mid + 1;
}
return r;
}
bool check(int r, vector<int>& houses, vector<int>& heaters) {
for (int i = 0, j = 0; i < houses.size(); i ++) {
while (j < heaters.size() && houses[i] > heaters[j] + r) ++ j;
if (j < heaters.size() && heaters[j] - r <= houses[i] && houses[i] <= heaters[j] + r)
continue;
return false;
}
return true;
}
};
4、面试题 16.06. 最小差
(1)对数组排序,两个指针 i , j i,j i,j 分别指向两个数组,对于每一对 ( i , j ) (i,j) (i,j) ,如果 a [ i ] = = b [ j ] a[i]==b[j] a[i]==b[j],那么存在最小值 0 0 0,直接返回;如果不相等,那么首先更新答案 a n s ans ans,然后根据 a [ i ] a[i] a[i] 与 b [ j ] b[j] b[j] 的大小更新 ( i , j ) (i,j) (i,j)。
class Solution {
public:
int smallestDifference(vector<int>& a, vector<int>& b) {
sort(a.begin(), a.end());
sort(b.begin(), b.end());
long long ans = 2147483650;
int i = 0, j = 0;
while (i < a.size() && j < b.size()) {
if ((long long)a[i] == (long long)b[j])
return 0;
else {
ans = min(ans, abs((long long)a[i] - (long long)b[j]));
a[i] > b[j] ? ++ j : ++ i;
}
}
return ans;
}
};
结语
2点睡,5点起,感觉要飞升了。补觉去了。