当前位置: 首页 > news >正文

蓝桥杯[每日两题] 练习题:盛最多水的容器 三数之和(java版)

题目链接

1.盛最多水的容器:11. 盛最多水的容器 - 力扣(LeetCode)

2.三数之和: 15. 三数之和 - 力扣(LeetCode)

题目一:盛最多水的容器 

题目描述

给定一个长度为 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。

示例2

输入:height = [1,1]
输出:1

 解题思路

我们最容易想到的就是暴力枚举每一种情况,然后计算出面积最大的结果。但是暴力很容易就超时了,所以我们考虑换一种思路。

这道题标签既然是双指针,而且要计算面积,那么就定左右指针,分别指向左右两端,这样就把要计算的容器给框出来了。

我们先搞清楚一个前提:容器的高度是由较高的边确定,还是较低的边确定呢?我们就拿示例1来讲,如图

自然是以较低的边来确定高度,这样才能把水装住。在上图这种情况下,我们发现此时底边是最长的。那还有没有必要拿第一个柱子和其他柱子计算容量呢?假使随机选择一根

这个时候,我们发现:

高度没变,底边倒是变短了,那体积自然就缩小了。 

 所以我们现在可以回答这个问题了:那还有没有必要拿第一个柱子和其他柱子计算容量呢?

答案是:没有必要了!

因为我们发现,拿较低的那根柱子和其他柱子去组成容器的话,高度是以较低的那根柱子决定的,即便我们找出的柱子高度很高,那最终还是要以这根低的为准,同时底边缩小了;如果找到了更低的柱子和这根柱子组合,那高度岂不是更低了吗,体积就更小了。所以我们大胆地提出一种思路:

①先定义左右指针,分别指向数组两端;

②然后我们计算得到一个值。

③之后将左右两根柱子高度做比较,如果左边更低的话, 那就没必要将左边的柱子和其他柱子组合了,那么就移动左边柱子;否则移动右边柱子;

④循环第③步,每次都计算出一个体积值,取最大值即可。

简单来说,其实就是排除了一些更小的数据,只需要考虑较大的那部分。 

其实我也是参考的评论区大神题解,这里有动图:

11. 盛最多水的容器 - 力扣(LeetCode)

代码实现 

class Solution {
    public int maxArea(int[] nums) {
       //双指针
       int left=0;
       int right=nums.length-1;
       int area=0;
       while(left<right){
        int temp=(right-left)*Math.min(nums[left],nums[right]);
        area=Math.max(area,temp);
        if(nums[left]>nums[right])
            right--;
        else left++;
       } 
       return area;
    }
}

 题目二:三数之和

题目描述

给你一个整数数组 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] 。

注意,输出的顺序和三元组的顺序并不重要。 

示例2

输入:nums = [0,1,1]
输出:[]
解释:唯一可能的三元组和不为 0 。

示例3

输入:nums = [0,0,0]
输出:[[0,0,0]]
解释:唯一可能的三元组和为 0 。

 解题思路

这道题官方给的标签依然是双指针。

①先对数组进行升序排序。

②然后固定一个数,下标为i,之后定义左指针为i+1,右指针指向最后一个数。如果固定的这个数与它前一个数相等,说明之前已经统计过了,跳过。

③在“左指针小于右指针”的前提下,先判断固定的这个数是否大于0。

④如果它都大于0了,那后面的肯定更是大于0,加起来不可能为0的,此时直接跳出循环就好。

⑤如果结果小于0,说明需要找到更大的数,那么就移动左指针;如果结果大于0,说明需要缩小一点,就移动右指针。

⑥搜集到一组结果之后,要对剩余的两个数做“去重”操作:如果左指针指向的数与它后一个数相等,移动左指针;如果右指针指向的数与它前面的数相等,移动右指针。因为相同的数已经计算过了,再计算就重复了。

代码实现

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

class Main {
    public static void main(String[] args) {
        List<List<Integer>> lists = threeSum(new int[]{-1, 0, 1, 2, -1, -4});
        System.out.println(lists);
    }

    public static List<List<Integer>> threeSum(int[] nums) {
        //排序
        Arrays.sort(nums);

        //遍历每一个数
        int length = nums.length;
        List<List<Integer>> resultList = new ArrayList<>();
        for (int i = 0; i < length; i++) {
            //收取结果后,去重
            if (i > 0 && nums[i] == nums[i - 1])
                continue;
            //最小的数都大于0了,后面的就不用看了
            if (nums[i] > 0)
                break;
            //找其余两个数
            int left = i + 1;
            int right = length - 1;
            while (left < right) {
                //看是否等于0
                if (nums[i] + nums[left] + nums[right] > 0)
                    right--;
                else if (nums[i] + nums[left] + nums[right] < 0)
                    left++;
                else {
                    resultList.add(Arrays.asList(nums[i], nums[left], nums[right]));
                    //对中间数去重
                    while (left < right && nums[left] == nums[left + 1])
                        left++;
                    while (left < right && nums[right] == nums[right - 1])
                        right--;
                    left++;
                    right--;
                }
            }

        }
        return resultList;
    }
}

相关文章:

  • flutter的HTTP headers用法介绍
  • 【组件安装】Rocky 8.10 安装Local License Server 25.03.0 for Linux
  • Python基本语法——变量
  • Conda环境搭建实战指南:打造高效开发环境
  • DeepSeek开源Day2:DeepEP技术详解
  • Ae 效果详解:VR 降噪
  • tkinter上canvas展示图片报错(mac系统)
  • 【人工智能】随机森林的智慧:集成学习的理论与实践
  • Linux练级宝典->Linux进程概念介绍
  • ROS2学习笔记2
  • 使用Vue CLI从零搭建企业级项目实战(Vue3+全家桶)
  • 【Axure原型分享】数字滚动——同时滚动效果
  • UIToolkit(一)
  • 【redis】pipeline管道
  • 第八章:C++ 实践
  • 调试正常 ≠ 运行正常:Keil5中MicroLIB的“量子态BUG”破解实录
  • 【Java面试题汇总】Java面试100道最新合集!
  • 笔记六:单链表链表介绍与模拟实现
  • cocos creator使用mesh修改图片为圆形,减少使用mask,j减少drawcall,优化性能
  • Linux 进程信息查看
  • 人民日报头版:紧盯“学查改”,推动作风建设走深走实
  • 一条铺过11年时光的科学红毯,丈量上海科创的“长宽高”
  • 竞彩湃|欧联杯决赛前,曼联、热刺继续划水?
  • 习近平向多哥新任领导人致贺电
  • “中国神湖”加快放大资源规模!3亿美元换海外年产380万吨钾盐项目
  • “女硕士失踪13年生两孩”案进入审查起诉阶段,哥哥:妹妹精神状态好转