剑指Offer | day12_双指针(快排那一套)
剑指 Offer 58 - I. 翻转单词顺序
输入一个英文句子,翻转句子中单词的顺序,但单词内字符的顺序不变。为简单起见,标点符号和普通字母一样处理。例如输入字符串"I am a student. ",则输出"student. a am I"。
示例 :
输入: " hello world! "
输出: "world! hello"
说明:
- 无空格字符构成一个单词。
- 输入字符串可以在前面或者后面包含多余的空格,但是反转后的字符不能包括。
- 如果两个单词间有多余的空格,将反转后单词间的空格减少到只含一个。
方法:
- 处理空格
- 按格式输出
class Solution {
public:
string reverseWords(string s) {
vector<string> v;
// 处理空格,原字符串后加一个空格更方便处理
s += ' ';
string str = "";
for(char ch : s) {
if(ch == ' ') {
if(!str.empty()) {
v.push_back(str);
str.clear();
}
}
else str += ch;
}
// 特殊情况
if(v.empty()) return "";
// 按格式输出字符串,注意最后一个输出的字符串不需要后接空格
str.clear();
for(int i = v.size() - 1; i > 0; i--) {
str += v[i];
str += ' ';
}
return str + v[0];
}
};
c++写字符串的题就看这儿:
剑指 Offer 57. 和为s的两个数字
输入一个递增排序的数组和一个数字s,在数组中查找两个数,使得它们的和正好是s。如果有多对数字的和等于s,则输出任意一对即可。
示例 :
输入:nums = [10,26,30,31,47,60], target = 40
输出:[10,30] 或者 [30,10]
限制:
1 <= nums.length <= 10^51 <= nums[i] <= 10^6
方法:二分查找(超时)
class Solution {
public:
vector<int> twoSum(vector<int>& nums, int target) {
for(int i = 0; i < nums.size()-1; i++) {
int val = target - nums[i];
int res = binary(nums, i+1, nums.size()-1, val);
if(res != -1) {
return {nums[i], nums[res]};
}
}
return {};
}
int binary(vector<int> nums, int l, int r, int val) {
if(l > r) return -1;
int mid = l + ((r - l) >> 1);
if(nums[mid] == val) {
return mid;
}
else if(nums[mid] > val) {
return binary(nums, l, mid-1, val);
}
else {
return binary(nums, mid+1, r, val);
}
}
};
- 时间复杂度:O(nlogn)
- 空间复杂度:O(1)
方法:双指针(类似快排)
class Solution {
public:
vector<int> twoSum(vector<int>& nums, int target) {
int l = 0;
int r = nums.size()-1;
while(l < r) {
if(target == nums[l] + nums[r]) {
return vector<int>{nums[l], nums[r]};
}
else if(target > nums[l] + nums[r]) {
l++;
}
else if(target < nums[l] + nums[r]) {
r--;
}
}
return {};
}
};
- 时间复杂度:O(n)
- 空间复杂度:O(1)
二分查找的两种写法:
- 递归
int binarySortRecursive(int num[], int l, int r, int val) {
if (l > r) return -1;
int mid = l + ((r - l) >> 1);
if (num[mid] == val) {
return mid;
}
else if (num[mid] > val) {
return binarySortRecursive(num, l, mid - 1, val);
}
else {
return binarySortRecursive(num, mid + 1, r, val);
}
}
- 非递归
int binarySort(int num[], int l, int r, int val) {
while (l <= r) {
int mid = l + ((r - 1) >> 1);
if (num[mid] == val) {
return mid;
}
else if (num[mid] > val) {
r = mid - 1;
}
else {
l = mid + 1;
}
}
return -1;
}
剑指 Offer 21. 调整数组顺序使奇数位于偶数前面
输入一个整数数组,实现一个函数来调整该数组中数字的顺序,使得所有奇数位于数组的前半部分,所有偶数位于数组的后半部分。
示例:
输入:nums = [1,2,3,4]
输出:[1,3,2,4]
注:[3,1,2,4] 也是正确的答案之一。
提示:
0 <= nums.length <= 500000 <= nums[i] <= 10000
方法:双指针
class Solution {
public:
vector<int> exchange(vector<int>& nums) {
int l = 0;
int r = nums.size() - 1;
while (l < r) {
// 超级注意! && 右边的表达式一定要正确的添加括号,不然运算优先级会乱掉
while (l < r && (nums[l]&1) == 1) {
l++;
}
while (l < r && (nums[r]&1) == 0) {
r--;
}
if (l < r) {
int temp = nums[l];
nums[l] = nums[r];
nums[r] = temp;
l++;
r--;
}
}
return nums;
}
};
- 时间复杂度:O(n)
- 空间复杂度:O(1)

浙公网安备 33010602011771号