两指针相向而行
反转字符串
编写一个函数,其作用是将输入的字符串反转过来。输入字符串以字符数组char[的形式给出。不要给另外的数组分配额外的空间,你必须原地修改输入数组、使用O(1)的额外空间解决这一问题。
你可以假设数组中的所有字符都是ASCII码表中的可打印字符。
实例:
题解:
class Solution {
public:
void reverseString(vector<char>& s) {
//反转字符串
int n = s.size();
//双指针
int left = 0;
int right = n-1;
while(true){
if(s[left]!=s[right]){
//交换
swap(s[left],s[right]);
}
left++;
right--;
//党right小于等于left时结束
if(right<=left){
break;
}
}
}
};
数组拆分
题解:
class Solution {
public:
int arrayPairSum(vector<int>& nums) {
//排序然后取偶数下标对应数值之和
sort(nums.begin(),nums.end());
int sum = 0;
for(int i = 0;i<nums.size();i=i+2){
sum += nums[i];
}
return sum;
}
};
自己实现快排(双指针思想):
class Solution {
public:
//快排实现
void quickSort(int *array, int left, int right){
if(left < right)
{
int pivot = array[left];
int low = left, high = right;
while(low < high)
{
while(array[high] >= pivot && low < high)
high--;
array[low] = array[high];
while(array[low] <= pivot && low < high)
low++;
array[high] = array[low];
}
array[low] = pivot;
quickSort(array, left, low - 1);
quickSort(array, low + 1, right);
}
}
int arrayPairSum(vector<int>& nums) {
//排序然后取偶数下标对应数值之和
// sort(nums.begin(),nums.end());
//快排
quickSort(&nums[0],0,nums.size()-1);
int sum = 0;
for(int i = 0;i<nums.size();i=i+2){
sum += nums[i];
}
return sum;
}
};
结果:
两数之和II:输入有序数组
一个已按照升序排列的整数数组numbers,请你从数组中找出两个数满足相加防和等于目标数 target 。
函数应该以长度为2的整数数组的形式返回这两个数的下标值。numbers 的下标从1开始计数,所以答案数组应当满足1<=answer[0]< answer[1]<= numbers.length。
你可以假设每个输入只对应唯一的答案,而且你不可以重复使用相同的元素。
实例:
题解:左右两个指针 两指针所指之数的和 若大于目标值 right-- 若小于目标值 left++
class Solution {
public:
vector<int> twoSum(vector<int>& numbers, int target) {
//下标从1开始 返回的时候加1即可
//左右两个指针 两指针所指之数的和 若大于目标值 right-- 若小于目标值 left++
int n = numbers.size();
//数组保存答案
vector<int> result;
//双指针
int left = 0;
int right = n-1;
while(left<right){
if(numbers[left]+numbers[right]>target){
//大于 数值需要减少
right--;
continue;
}else if(numbers[left]+numbers[right]<target){
//小于 数值需要增加
left++;
continue;
}else{
//相等
result.push_back(left+1);
result.push_back(right+1);
break;
}
}
return result;
}
};
快慢指针 同向而行
移除元素
实例:
题解:
class Solution {
public:
int removeElement(vector<int>& nums, int val) {
//返回移除元素后的数组的长度 并且数组在改长度范围的元素符合要求
//长度
int n = nums.size();
//快指针 慢指针
int fast = 0;
int slow = 0;
for(fast = 0;fast<n;fast++){
if(nums[fast] != val){
//不等 赋值
nums[slow] = nums[fast];
//移动慢指针
slow++;
}
}
return slow;
}
};
最大连续1的个数
题解:
class Solution {
public:
int findMaxConsecutiveOnes(vector<int>& nums) {
//长度
int n = nums.size();
//快慢指针
int fast = 0;
int slow = 0;
//使用一个变量来记录最大连续1的个数
int maxCount = 0;
while(fast<n){
//找到每一段的第一个1
while(nums[fast] == 0) {
//不是最后一个数
if((fast+1)<n){
fast++;
}else{
//是最后一个数 且该值为0
return maxCount;
}
}
//出了循环 此时fast指向了第一个1 将其下标赋值给slow
slow = fast;
//fast继续遍历 直到遇到0
while(nums[fast] == 1){
if((fast+1)<n){
fast++;
}else{
//最后一个数 且为1
int num = fast - slow+1;
if(num>maxCount){
maxCount = num;
}
return maxCount;
}
}
//找到连续1后的第一个0
//此时fast指向了0
int num = fast-slow;
if(num>maxCount){
maxCount = num;
}
}
return maxCount;
}
};
长度最小的子数组
题解:
class Solution {
public:
int minSubArrayLen(int target, vector<int>& nums) {
//长度最小的子数组
int n = nums.size();
//快慢指针
int fast = 0;
int slow = 0;
//长度最小子数组
int minLen = n+1;
if(nums[fast]>=target){
return 1;
}
int sum = nums[fast];
fast++;
while(fast<n && slow<n){
while(sum+nums[fast]<target && (fast+1)<n){
//更新和值
sum += nums[fast];
fast++;
}
if(fast+1>=n){
if(sum+nums[fast]>=target){
int num = fast-slow+1;
if(num<minLen){
minLen = num;
}
//fast不能再++了 但是slow还可以
sum = sum + nums[fast];
while(sum>=target) {
if(slow+1<n){
sum -= nums[slow];
slow++;
}else{
//等于 最后一个数直接大于等于目标值
return 1;
}
}
//不大于了
num = fast-(slow-1)+1;
if(num<minLen){
minLen = num;
}
return minLen;
}else{
return (minLen == n+1)?0:minLen;
}
}
if(sum+nums[fast]>=target){
//大于等于了
int num = fast-slow+1;
cout<<"fast:"<<fast<<"slow:"<<slow;
if(num<minLen){
minLen = num;
}
//减少和的值
sum = sum - nums[slow];
slow++;
}
}
return (minLen == n+1)?0:minLen;
}
};