leetcode15.三数之和
给你一个包含 n 个整数的数组 nums,判断 nums 中是否存在三个元素 a,b,c ,使得 a + b + c = 0 ?请你找出所有和为 0 且不重复的三元组。
func threeSum(nums []int) [][]int {
n := len(nums)
sort.Ints(nums)
ans := make([][]int, 0)
// 枚举 a
for first := 0; first < n; first++ {
// 需要和上一次枚举的数不相同
if first > 0 && nums[first] == nums[first - 1] {
continue
}
// c 对应的指针初始指向数组的最右端
third := n - 1
target := -1 * nums[first]
// 枚举 b
for second := first + 1; second < n; second++ {
// 需要和上一次枚举的数不相同
if second > first + 1 && nums[second] == nums[second - 1] {
continue
}
// 需要保证 b 的指针在 c 的指针的左侧
for second < third && nums[second] + nums[third] > target {
third--
}
// 如果指针重合,随着 b 后续的增加
// 就不会有满足 a+b+c=0 并且 b<c 的 c 了,可以退出循环
if second == third {
break
}
if nums[second] + nums[third] == target {
ans = append(ans, []int{nums[first], nums[second], nums[third]})
}
}
}
return ans
}
当我们需要枚举数组中的两个元素时,如果我们发现随着第一个元素的递增,第二个元素是递减的,那么就可以使用双指针的方法,将枚举的时间复杂度从 O(N^2)减少至 O(N)。
leetcode334——双指针的贪心算法
- 题目描述
给你一个整数数组 nums ,判断这个数组中是否存在长度为 3 的递增子序列。
如果存在这样的三元组下标 (i, j, k) 且满足 i < j < k ,使得 nums[i] < nums[j] < nums[k] ,返回 true ;否则,返回 false 。
- 贪心思路:
用一个small和一个mid指针记录当前遇到的x和y。然后遍历数组,不断更新small和mid的值,一旦遇到了某个数大于mid,那么就表示成功找到了三元组,可以返回true;
- 关键
如果更新了small之后,导致small的位置在mid之后怎么办?
没有影响,因为有没有需要的三元组存在,是取决于mid。即使更新后的small在mid后面,那也一定有一个旧的small在mid前面,所以可以返回true。代码如下:
class Solution {
public:
bool increasingTriplet(vector<int>& nums) {
int n = nums.size();
if(n < 3) return false;
int small = INT_MAX;
int mid = INT_MAX;
for(auto num : nums){
if(num <= small){
small = num;
}
else if(num <= mid){
mid = num;
}
else if(num > mid){
return true;
}
}
return false;
}
};