文章目录
- 0. Leetcode [917. 仅仅反转字母](https://leetcode-cn.com/problems/reverse-only-letters/)
- 1. Leetcode [167. 两数之和 II - 输入有序数组](https://leetcode-cn.com/problems/two-sum-ii-input-array-is-sorted/)
- 2. Leetcode [165. 比较版本号](https://leetcode-cn.com/problems/compare-version-numbers/)
- 3. Leetcode [443. 压缩字符串](https://leetcode-cn.com/problems/string-compression/solution/ya-suo-zi-fu-chuan-by-leetcode-solution-kbuc/)
- 总结
0. Leetcode 917. 仅仅反转字母
分析与解答
借用双指针的思想,要调换单词中所有字母的顺序,只需要首尾配对找到相应字母位置即可。因此令 i 从头开始,j 从尾开始寻找字母,找到后进行调换,直至 i >= j,表明已交换单词中的所有字母。
class Solution {
public:
string reverseOnlyLetters(string s) {
for (int i = 0, j = s.size() - 1; i < j;) {
while (!(tolower(s[i]) >= 'a' && tolower(s[i]) <= 'z') && i < j) {
i++;
}
while (!(tolower(s[j]) >= 'a' && tolower(s[j]) <= 'z') && i < j) {
j--;
}
if (i >= j) {
break;
} else {
char tmp = s[i];
s[i] = s[j];
s[j] = tmp;
}
// 交换完后将指针移到下一个待判断字符
i++;
j--;
}
return s;
}
};
算法时间复杂度为 O ( N ) O(N) O(N)
1. Leetcode 167. 两数之和 II - 输入有序数组
分析与解答
解法1:二分查找
对于该问题,从头至尾遍历数组,对每个数 num
,二分查找 target - num
在数组中是否存在。
class Solution {
public:
int findPos(vector<int>& numbers, int low, int high, int target) {
int l(low), r(high);
while (l <= r) {
int mid = l + ((r - l) >> 1);
if (numbers[mid] < target) {
l = mid + 1;
} else if (numbers[mid] > target) {
r = mid - 1;
} else {
return mid;
}
}
return -1;
}
vector<int> twoSum(vector<int>& numbers, int target) {
vector<int> result;
bool find(false);
for (int i = 0; i < numbers.size(); ++i) {
int idx = findPos(numbers, i+1, numbers.size() - 1, target - numbers[i]);
if (idx > 0) {
result.push_back(i+1);
result.push_back(idx+1);
break;
}
}
return result;
}
};
算法时间复杂度为
O
(
N
l
o
g
N
)
O(NlogN)
O(NlogN)
解法2:双指针
令两个指针分别指向首数字与尾数字,若两数和大于 target
,则尾指针前移;若两数和大于 target
,则首指针后移。
class Solution {
public:
vector<int> twoSum(vector<int>& numbers, int target) {
vector<int> result;
int i(0), j(numbers.size() - 1);
while (i < j) {
if (numbers[i] + numbers[j] < target) {
i++;
} else if (numbers[i] + numbers[j] > target) {
j--;
} else {
result.push_back(i + 1);
result.push_back(j + 1);
break;
}
}
return result;
}
};
算法时间复杂度为 O ( N ) O(N) O(N)
2. Leetcode 165. 比较版本号
分析与解答
令两个指针指向字符串头,后移指针 r
,直至找到字符 .
,此时从指针间取出字串,进行比较。重复这一过程直至遍历完成。
class Solution {
public:
int compareVersion(string version1, string version2) {
int l0(0), r0(0);
int l1(0), r1(0);
int result(0);
version1 += ".";
version2 += ".";
while (r0 < version1.size() || r1 < version2.size()) {
string str1 = "0";
string str2 = "0";
if (r0 < version1.size()) {
while (version1[r0] != '.') {
r0++;
}
while (version1[l0] == '0') {
l0++;
}
if (r0 - l0 > 0) {
str1 = version1.substr(l0, r0 - l0);
}
}
if (r1 < version2.size()) {
while (version2[r1] != '.') {
r1++;
}
while (version2[l1] == '0') {
l1++;
}
if (r1 - l1 > 0) {
str2 = version2.substr(l1, r1 - l1);
}
}
if (stoi(str1) < stoi(str2)) {
result = -1;
break;
} else if (stoi(str1) > stoi(str2)) {
result = 1;
break;
}
r0++;
l0 = r0;
r1++;
l1 = r1;
}
return result;
}
};
算法时间复杂度为 O ( N ) O(N) O(N)
3. Leetcode 443. 压缩字符串
分析与解答
令指针 i
作为写指针,记录写字符的位置;指针 j
作为读指针,记录读取字符的位置,后移指针 j
直至新字符与前一字符不同,此时用指针 i
写入。重复该过程直至遍历完成。
class Solution {
public:
int compress(vector<char>& chars) {
int i(0), j(1);
char preChar = chars[0];
int count = 1;
string cstr;
while (j < chars.size()) {
if (preChar != chars[j]) {
chars[i++] = preChar;
if (count > 1) {
cstr = to_string(count);
for (int k = 0; k < cstr.size(); ++k) {
chars[i++] = cstr[k];
}
}
preChar = chars[j];
count = 1;
} else {
count++;
}
j++;
}
chars[i++] = preChar;
if (count > 1) {
cstr = to_string(count);
for (int k = 0; k < cstr.size(); ++k) {
chars[i++] = cstr[k];
}
}
return i;
}
};
算法时间复杂度为 O ( N ) O(N) O(N)
总结
用好双指针能够有效降低时间复杂度,简化问题。