五月集训(第05天)——双指针
双指针
1. 917. 仅仅反转字母
思路:
left
往右找字母,right
往左找字母,两个都找到后交换位置,继续移动指针
class Solution {
public:
string reverseOnlyLetters(string s) {
int len = s.length();
int left = 0, right = len - 1;
char temp;
while (left < right) {
while (!((s[left] >= 'a' && s[left] <= 'z') || (s[left] >= 'A' && s[left] <= 'Z'))) {
left++;
if (left >= right) break;
}
while (!((s[right] >= 'a' && s[right] <= 'z') || (s[right] >= 'A' && s[right] <= 'Z'))) {
right--;
if (left >= right) break;
}
if (left >= right) break;
temp = s[left];
s[left] = s[right];
s[right] = temp;
left ++;
right --;
}
return s;
}
};
2. 167. 两数之和 II - 输入有序数组
思路:
利用left
和right
两个指针从数组的首尾向中间移动,和大于目标值,right
左移,和小于目标值left
右移。
class Solution {
public:
vector<int> twoSum(vector<int>& numbers, int target) {
int left = 0, right = numbers.size() - 1;
vector<int> ans;
while (left < right) {
if (numbers[left] + numbers[right] == target) break;
else if (numbers[left] + numbers[right] < target) left ++;
else if (numbers[left] + numbers[right] > target) right --;
}
ans.push_back(left + 1);
ans.push_back(right + 1);
return ans;
}
};
3. 165. 比较版本号
思路:
没用上双指针,直接字符串处理了,思路在代码注释里
class Solution {
public:
void GetVersion(vector<string> &ver, string version, int len) {
string temp;
int flag = 0;
for (int i = 0; i < len; i++) {
if (version[i] == '.') {
if (temp != "") ver.push_back(temp);
else ver.push_back("0");
flag = 0;
temp = "";
}
else {
while (flag == 0) {
if (version[i] != '0') flag = 1;
else i ++;
}
if (version[i] != '.') temp.push_back(version[i]);
else i--;
}
}
}
int Cmp_Ver(vector<string> &ver1, vector<string> &ver2) {
int size1 = ver1.size(), size2 = ver2.size();
int minn = fmin(size1, size2);
int len1, len2;
// 首先将相同部分的修订号比大小
for (int i = 0; i < minn; i++) {
len1 = ver1[i].length();
len2 = ver2[i].length();
// 长度长的修订号更大(最高位更高)
if (len1 != len2) return len1 > len2 ? 1 : -1;
else { // 长度相等话逐位比较
for (int j = 0; j < len1; j++) {
if (ver1[i][j] != ver2[i][j]) return ver1[i][j] > ver2[i][j] ? 1 : -1;
}
}
}
// 如果修订号的数量相同,且大小相等
if (size1 == size2) return 0;
else { // 如果前面部分修订号的都相同,就比较修订号更多的一个版本号多出来的修订号是否为0,有一个不为0,则更大
if (size1 < size2) {
for (int i = minn; i < size2; i++) {
if (ver2[i] != "0") return -1;
}
} else {
for (int i = minn; i < size1; i++) {
if (ver1[i] != "0") return 1;
}
}
}
return 0;
}
int compareVersion(string version1, string version2) {
vector<string> ver1;
vector<string> ver2;
version1 += '.';
version2 += '.';
int len_ver1 = version1.length();
int len_ver2 = version2.length();
// 将version1的每个修订号(去掉前导零、如果全为0,则该修订号记为0)放入数组ver1
GetVersion(ver1, version1, len_ver1);
// 将version2的每个修订号(去掉前导零、如果全为0,则该修订号记为0)放入数组ver2
GetVersion(ver2, version2, len_ver2);
// 返回比较结果
return Cmp_Ver(ver1, ver2);
}
};
4. 443. 压缩字符串
思路:
一边统计字母个数,一边在另一个vector
存储答案。本来这应该是双指针问题,但是今天状态不好,直接大模拟了,收工,要去复习了,还有两门考试在等我,呜呜呜。
class Solution {
public:
int compress(vector<char>& chars) {
int n = chars.size();
int cnt = 1;
vector<char> ans;
ans.push_back(chars[0]);
for (int i = 1; i < n; i++) {
if (chars[i] == ans[ans.size() - 1]) {
cnt ++;
}
if (i == n - 1 || chars[i] != ans[ans.size() - 1]) {
if (cnt < 10 && cnt > 1) ans.push_back(cnt + '0');
else if (cnt >= 10) {
int temp = 0;
int len = 0;
while (cnt) {
len ++;
temp = temp * 10 + cnt % 10;
cnt /= 10;
}
while (temp) {
len --;
ans.push_back(temp % 10 + '0');
temp /= 10;
}
while (len --) {
ans.push_back('0');
}
}
if (chars[i] != chars[i - 1]) ans.push_back(chars[i]);
cnt = 1;
}
}
chars.clear();
for (int i = 0; i < ans.size(); i++) chars.push_back(ans[i]);
return ans.size();
}
};
东方欲晓,莫道君行早。