字符串回顾:
-
字符串是若干字符组成的有限序列,也可以理解为是一个字符数组
-
在C语言中,把一个字符串存入一个数组时,也把结束符 '\0'存入数组,并以此作为该字符串是否结束的标志。
-
c++ 中,字符串提供了一个size的接口,可以判断字符串长度:
string a = "string"; for (int i = 0; i < a.size(); i++) { }
字符串出现过的题目
-
反转字符串:使用双指针法实现了反转字符串的操作,双指针法在数组,链表和字符串中很常用。
-
使用双指针法在时间复杂度O(n)的情况下完成替换空格。
-
其实很多数组填充类的问题,都可以先预先给数组扩容带填充后的大小,然后在从后向前进行操作。
-
使用双指针法进行移除操作。
-
所以,双指针法是字符串处理的常客。
双指针复习
在以下几种情况下,都用到了双指针:
-
数组
-
移除元素
-
-
字符串
-
反转字符串
-
替换数字
-
-
链表
-
反转链表
-
-
N数之和
-
三数之和
-
里面大多数题目,我都在前几个博客写过了,这次写两个之前没写过的题目。
15. 三数之和(双指针)
给你一个包含 n 个整数的数组 nums,判断 nums 中是否存在三个元素 a,b,c ,使得 a + b + c = 0 ?请你找出所有满足条件且不重复的三元组。
注意: 答案中不可以包含重复的三元组。
示例:
给定数组 nums = [-1, 0, 1, 2, -1, -4],
满足要求的三元组集合为: [ [-1, 0, 1], [-1, -1, 2] ]
哈希表思路:(不建议)
-
求两数之和:a+b=0,我们用map来存放遍历过的元素
-
那么三数之和,我们求 a+b+c=0,相比于两数之和的难点在于,三数之和需要去重
-
解题思路如下:去寻找0-(a+b) 是否在map里
-
但是这里用哈希法有些难,因为我们需要给a和b去重,去重的可能性非常多,所以很复杂,因此不建议用哈希法来做
双指针法思路: (推荐做法)
-
我们有一个数组,然后要在这个数组里找到 a+b+c=0
-
然后我们给这个数组排序(递增),(这里我们需要找到三个元素值,而不需要返回下标,所以我们可以先给这个数组排序)
-
为什么要排序?
-
排序之后,我们用一个for循环,遍历i的位置,得到a(i从第一位开始),然后i的第二位开始为left,末位为right
-
然后我们判断:nums[i] + nums[left] + nums[right] 是否 >0
-
如果三数相加>0, 那么right-- (right往左移动一位,让和变小一点)
-
如果三数相加<0, 那么left++ (left往右移动一位,让和变大一点)
-
如果三数相加=0,那就把此时的 nums[i], nums[left], nums[right] 存放到result数组里
-
-
去重:要给abc去重,不能在result中出现重复的元素
伪代码
// 1. 排序
sort(nums);
for(i=0; i<nums.size(); i++){
if(nums[i]>0){ // 如果第一个数组大于0,直接返回
return
}
if(i>0 && nums[i] == nums[i-1]) { continue };
left = i+1;
right = nums.size()-1;
while(right > left){
if(nums[i] + nums[left] + nums[right] > 0):
right--;
else if(nums[i] + nums[left] + nums[right] <0):
left++;
else:
result.push(nums[i], nums[left], nums[right]);
// 去重
}
}