解题4.3

文章介绍了在给定有序数组中找到和为目标值的两个数(两数之和),以及在一组整数中找到和为零的三个数(三数之和)的算法,同时讨论了如何计算容器能容纳的最大水量(盛最多水的容器)。解决方案都利用了双指针策略和对数组有序性的利用。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

167. 两数之和 II - 输入有序数组

给你一个下标从 1 开始的整数数组 numbers ,该数组已按 非递减顺序排列  ,请你从数组中找出满足相加之和等于目标数 target 的两个数。如果设这两个数分别是 numbers[index1] 和 numbers[index2] ,则 1 <= index1 < index2 <= numbers.length 。

以长度为 2 的整数数组 [index1, index2] 的形式返回这两个整数的下标 index1  index2

你可以假设每个输入 只对应唯一的答案 ,而且你 不可以 重复使用相同的元素。

你所设计的解决方案必须只使用常量级的额外空间。

示例 1:

输入:numbers = [2,7,11,15], target = 9
输出:[1,2]
class Solution {
public:
    vector<int> twoSum(vector<int>& numbers, int target) {
           sort(numbers.begin(),numbers.end());
           int star = 0,end = numbers.size() - 1;
           while(star < end)
           {
            if(numbers[star] + numbers[end] == target)return {star+1,end+1};
            if(numbers[star] + numbers[end] > target)end --;
            else star ++;
           }
           return {};
    }
};

 根据题意可知,一个numbers 数组一定有两个数加起来等于 target

所以我们先将numbers 进行一个排序。然后设置一个头尾指针。

那么可得 如果  头 + 尾  >  目标值   那么这个数一定在 尾 部的前面 因为 尾部后面的数 + 头 一定大于 目标值;   同理 如果 头 + 尾  <  目标值 那么一定在头的前面;

15. 三数之和

给你一个整数数组 nums ,判断是否存在三元组 [nums[i], nums[j], nums[k]] 满足 i != ji != k 且 j != k ,同时还满足 nums[i] + nums[j] + nums[k] == 0 。请

你返回所有和为 0 且不重复的三元组。

注意:答案中不可以包含重复的三元组。

示例 1:

输入:nums = [-1,0,1,2,-1,-4]
输出:[[-1,-1,2],[-1,0,1]]
解释:
nums[0] + nums[1] + nums[2] = (-1) + 0 + 1 = 0 。
nums[1] + nums[2] + nums[4] = 0 + 1 + (-1) = 0 。
nums[0] + nums[3] + nums[4] = (-1) + 2 + (-1) = 0 。
不同的三元组是 [-1,0,1] 和 [-1,-1,2] 。
注意,输出的顺序和三元组的顺序并不重要。
class Solution {
public:
    vector<vector<int>> threeSum(vector<int>& nums) {
     sort(nums.begin(),nums.end());
     vector<vector<int>> ans;
     int n=nums.size();
     int star,end;
     int i;
     for(i = 0; i < n - 2 ;i += 1)
     {
        if(i && nums[i] == nums[i - 1])continue; //如果数相同就跳过
        star = i + 1;
        end = n - 1;
        if(nums[end - 1] + nums[end] + nums[i] < 0)continue; //最大的三个数加起来都比 0小
        if(nums[star] + nums[i+2] + nums[i] > 0)break; //最小的三个数加起来都比 0大
        //后面的数相加一定大于0
        
        while(star < end)
        {
           
            if(nums[star] + nums[end] + nums[i] == 0)
            {
                ans.push_back({nums[star],nums[end],nums[i]});
                star ++,end --;
                while(star < end && nums[star - 1] == nums[star])star++;
                while(star < end && nums[end] == nums[end + 1])end --;
                
            }
            else 
            if(nums[star] + nums[end] + nums[i] < 0)
            star++;
            else 
            end --;
        }

     }
     return ans;
    }
};

可以看作   两数之和   的加强版,将一个固定的数看做目标状态。然后在剩下的数里面寻找

两个数 时的 两数之和 == -目标状态。后面的解法跟  两数之和   就基本没有区别了 ,不过

要注意的是没有重复;

11. 盛最多水的容器

给定一个长度为 n 的整数数组 height 。有 n 条垂线,第 i 条线的两个端点是 (i, 0) 和 (i, height[i]) 。

找出其中的两条线,使得它们与 x 轴共同构成的容器可以容纳最多的水。

返回容器可以储存的最大水量。

说明:你不能倾斜容器。

示例 1:

输入:[1,8,6,2,5,4,8,3,7]
输出:49 
解释:图中垂直线代表输入数组 [1,8,6,2,5,4,8,3,7]。在此情况下,容器能够容纳水(表示为蓝色部分)的最大值为 49。
class Solution {
public:
    int maxArea(vector<int>& height) {
        int star = 0,end = height.size() - 1,min_heig;
        int max = 0;
        while(star < end)
        {
            min_heig  = std::min(height[star],height[end]);
            max = std::max(max,min_heig * (end - star));
            if(height[star] < height[end])
            star+=1;
            else 
            end -=1;
        }
        return max;
    }
};

同样可以用双指针去做。 

证明:

容积 = 短的那段  * 他们的距离

 当 star,end 分别指向两端;

如果star 是短的那段,那么当end -= 1 时一定小于当前的值  因为容积 = 短的那段  * 他们的距离。

当end-=1;时 他们的距离 变短。 但是 后来短的那段 一定不会大于 当前 的star。所有可得end是不

可能移动的;

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值