前文回顾:力扣 | 数组和字符串简介
力扣LeetBook:数组和字符串
文章目录
- 📚双指针技巧:情形一
- 👉反转字符串
- 👉数组拆分I
- 👉两数之和 II - 输入有序数组
- 📚双指针技巧:情形二
- 👉移除元素
- 👉最大连续1的个数
- 👉长度最小的子数组⭐️
- 📚总结
- 👉杨辉三角
- 👉杨辉三角II
- 👉反转字符串中的单词 III
- 👉寻找旋转排序数组中的最小值
- 👉删除排序数组中的重复项
- 👉移动零
📚双指针技巧:情形一
反转数组中的元素。比如数组为 [‘l’, ‘e’, ‘e’, ‘t’, ‘c’, ‘o’, ‘d’, ‘e’],反转之后变为 [‘e’, ‘d’, ‘o’, ‘c’, ‘t’, ‘e’, ‘e’, ‘l’]。
使用双指针技巧,其思想是分别将两个指针分别指向数组的开头及末尾,然后将其指向的元素进行交换,再将指针向中间移动一步,继续交换,直到这两个指针相遇。
👉反转字符串
class Solution {
public:void reverseString(vector<char>& s) {if(s.size()==0) return ;for(int i=0,j=s.size()-1 ;i<j ; i++,j--) {char temp=s[i];s[i]=s[j];s[j]=temp;}}
};
👉数组拆分I
直接排序取奇数位要啥双指针
class Solution {
public:int arrayPairSum(vector<int>& nums) {sort(nums.begin(),nums.end());int sum=0;for(int i=0;i<nums.size();i+=2){//先排序然后取奇数位求和sum += nums[i];}return sum;}
};
👉两数之和 II - 输入有序数组
由于数组从小到大排列, 双指针分别指向首部和尾部;
- 首部尾部相加等于目标值,返回结果集
- 首部尾部相加小于目标值,首部后移变大
- 首部尾部相加大于目标值,尾部前移变小
class Solution {
public:vector<int> twoSum(vector<int>& numbers, int target) {int head=0,tail=numbers.size()-1;while(head<tail){if(numbers[head]+numbers[tail]<target){//首部尾部相加小于目标值,首部后移变大head++;}else if(numbers[head]+numbers[tail]>target){//首部尾部相加大于目标值,尾部前移变小tail--;}else{//首部尾部相加等于目标值,返回结果集return{head+1,tail+1};}}return{0,0};}
};
📚双指针技巧:情形二
有时,我们可以使用
两个不同步
的指针来解决问题,即快慢指针。与情景一不同的是,两个指针的运动方向是相同的,而非相反。让我们从一个经典问题开始:
- 给你一个数组 nums 和一个值 val,你需要
原地移除
所有数值等于 val 的元素,并返回移除后数组的新长度。
采用快慢指针的思想:初始化一个快指针 fast 和一个慢指针 slow,fast 每次移动一步,而 slow 只当 fast 指向的值不等于 val 时才移动一步。
👉移除元素
class Solution {
public:int removeElement(vector<int>& nums, int val) {int slow=0;for (int fast=0;fast<nums.size();fast++) {//fast 每次移动一步,//而 slow 只当 fast 指向的值不等于 val 时才移动一步。if(nums[fast]!=val) {nums[slow]=nums[fast];slow++;}}return slow;}
};
👉最大连续1的个数
class Solution {
public:int findMaxConsecutiveOnes(vector<int>& nums) {int res=0,temp=0;for(int i=0;i<nums.size();i++) {//记录连续1的个数并及时更新temp=(nums[i]==1)?(temp+1):0;res=max(res,temp);}return res;}
};
👉长度最小的子数组⭐️
参考讨论区大佬题解
——双指针+尺取法
class Solution {
public:int minSubArrayLen(int target, vector<int>& nums) {int fast=0,slow=0;//快慢指针int sum=0,length=nums.size()+1;//用于求和,最短长度更新for(;fast<nums.size();fast++){sum+=nums[fast];//快指针移动求和if(sum>=target) {//达到目标后进行收缩while(1){ //慢指针可以往后移动多少if(sum-nums[slow]>=target) {sum-=nums[slow];slow++;}else break;}if(fast-slow+1<length) length=fast-slow+1;//更新最小长度}}if(length<nums.size()+1) return length;//判断是否存在符合要求的子数组else return 0;}
};
📚总结
👉杨辉三角
class Solution {
public:vector<vector<int>> generate(int numRows) {vector<vector<int>> ret;//vector<int>(a, b)的意思是创建一个大小为 a的vector,并将其所有元素初始化为 b。//创建一个大小为1的vector,并将其所有元素初始化为1ret.push_back(vector<int>(1,1));//设定第一层for(int i=1;i<numRows;i++){vector<int> a(i+1);//每一层对应的数组for(int j=0;j<=i;j++){if(j==0||j==i) a[j]=1;else a[j]=ret[i-1][j-1]+ret[i-1][j];}ret.push_back(a);}return ret;}
};
👉杨辉三角II
参考讨论区【序散】
class Solution {
public:vector<int> getRow(int rowIndex) {//vector<int>(a, b)的意思是创建一个大小为 a的vector,并将其所有元素初始化为 b。vector<int> res(rowIndex+1,1);if (rowIndex<2) return res;//前两层都是1for(int i=1;i<rowIndex;i++){for(int j=i;j>0;j--)res[j]=res[j-1]+res[j];}return res;}
};
👉反转字符串中的单词 III
- 首先遍历整个字符串,找到每个单词的起始位置和结束位置。
- 然后对每个单词进行反转。
- 最后返回反转后的字符串。
class Solution {
public:string reverseWords(string s) {int i=0;int n=s.size();while(i<n) {int start=i;while(i<n && s[i]!=' ') {//找到单词的起始位置i++;}int end=i-1;// 反转单词while(start<end) {swap(s[start],s[end]);start++;end--;}i++; //下一个单词}return s;}
};
👉寻找旋转排序数组中的最小值
class Solution {
public:int findMin(vector<int>& nums) {//直接排序找最小sort(nums.begin(),nums.end());return nums[0];}
};
👉删除排序数组中的重复项
class Solution {
public:int removeDuplicates(vector<int>& nums) {int fast=0;int slow=0;while(fast<(nums.size()-1)){//双指针移动fast++;if(nums[fast]!=nums[fast-1]){slow++;nums[slow]=nums[fast];}}return (slow+1);}
};
👉移动零
class Solution {
public:void moveZeroes(vector<int>& nums) {int slow=0,fast=0;while(fast<nums.size()){//先排好所有非零元素if(nums[fast]!=0){nums[slow]=nums[fast];slow++;}fast++;}for(;slow<nums.size();slow++){//再补0nums[slow]=0;}}
};
代办清单👇