当前位置:   article > 正文

Java算法 盛最多水的容器(经典面试题)、三数之和(经典面试题)

Java算法 盛最多水的容器(经典面试题)、三数之和(经典面试题)

小王的Java刷题日记Day6

记录刷题过程,作为笔记和分享,坚持每天刷题,每天进步,编程语言为Java。

题目一:盛最多水的容器(经典面试题)

给定一个长度为 n 的整数数组 height 。有 n 条垂线,第 i 条线的两个端点是 (i, 0) 和 (i, height[i]) 。找出其中的两条线,使得它们与 x 轴共同构成的容器可以容纳最多的水。

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

例如:

输入:[1,8,6,2,5,4,8,3,7]
输出:49 

思路:双指针法    时间复杂度O(n)

设两指针 ij ,指向的水槽板高度分别为 h[i] , h[j] ,此状态下水槽面积为 S(i,j)。由于可容纳水的高度由两板中的 短板 决定,因此可得如下 面积公式 :S(i,j)=min(h[i],h[j])×(j−i)。

那么接下来就要解释一下解题的思路了:

1、首先,我们知道容纳水的高度由短板决定,那么此时我们通过对比左右两板的长度,也就是高度,让短的移动。

2、头尾都设置指针,不断向内移动。那么此时它的底是在不断减小的,我们只有让高变大才有可能总面积变大。所以我们要移动短板,每次移动后都要进行比较,不断让短板内移。

3、在内移的过程中比较每次变化的面积,并将最大的记录下来。

  1. class Solution {
  2. public int maxArea(int[] height) {
  3. int i=0,j=height.length-1,res=0;
  4. while(i<j){
  5. if(height[i]<height[j]){ //直到头尾指针相遇
  6. res=Math.max(res, (j - i) * height[i++]);
  7. }
  8. else{
  9. res=Math.max(res, (j - i) * height[j--]);
  10. }
  11. }
  12. return res;
  13. }
  14. }

题目二: 三数之和(经典面试题)

给你一个整数数组 nums ,判断是否存在三元组 [nums[i], nums[j], nums[k]] 满足 i != ji != kj != k ,同时还满足 nums[i] + nums[j] + nums[k] == 0 。请你返回所有和为 0 且不重复的三元组。

例如:

输入:nums = [-1,0,1,2,-1,-4]
输出:[[-1,-1,2],[-1,0,1]]

思路:排序,双指针法     时间复杂度O(n^2)

1、先进行排序,排序后我们固定一个数,让头尾指针指着其他两个数去移动,等相遇后我们再让固定的数向前移动。

2、

当 nums[k] > 0 时直接break跳出:因为 nums[j] >= nums[i] >= nums[k] > 0,即 3 个元素都大于 0 ,在此固定指针 k 之后不可能再找到结果了。

3、

当 k > 0且nums[k] == nums[k - 1]时即跳过此元素nums[k]:因为已经将 nums[k - 1] 的所有组合加入到结果中,本次双指针搜索只会得到重复组合。

4、

i,j 分设在数组索引 (k,len(nums))(k, len(nums))(k,len(nums)) 两端,当i < j时循环计算s = nums[k] + nums[i] + nums[j],并按照以下规则执行双指针移动:

当s < 0时,i += 1并跳过所有重复的nums[i];
当s > 0时,j -= 1并跳过所有重复的nums[j];
当s == 0时,记录组合[k, i, j]至res,执行i += 1和j -= 1并跳过所有重复的nums[i]和nums[j],防止记录到重复组合。

  1. class Solution {
  2. public List<List<Integer>> threeSum(int[] nums) {
  3. Arrays.sort(nums); // 对数组进行排序
  4. List<List<Integer>> res = new ArrayList<>(); // 存储结果的列表
  5. for(int k = 0; k < nums.length - 2; k++){ // 遍历数组,k表示三元组的第一个元素
  6. if(nums[k] > 0) break; // 如果当前元素大于0,后面的元素都会大于0,直接结束循环
  7. if(k > 0 && nums[k] == nums[k - 1]) continue; // 当前元素与上一个元素相同,避免重复计算,继续下一次循环
  8. int i = k + 1, j = nums.length - 1; // i为三元组的第二个元素,j为三元组的第三个元素
  9. while(i < j){ // 使用双指针法找到满足条件的三元组
  10. int sum = nums[k] + nums[i] + nums[j]; // 计算三个元素的和
  11. if(sum < 0){ // 如果和小于0,移动左指针,使得和增大
  12. while(i < j && nums[i] == nums[++i]); // 跳过重复的元素
  13. } else if (sum > 0) { // 如果和大于0,移动右指针,使得和减小
  14. while(i < j && nums[j] == nums[--j]); // 跳过重复的元素
  15. } else { // 如果和等于0,找到一个满足条件的三元组
  16. res.add(new ArrayList<Integer>(Arrays.asList(nums[k], nums[i], nums[j]))); // 将三元组加入结果列表
  17. while(i < j && nums[i] == nums[++i]); // 跳过重复的元素
  18. while(i < j && nums[j] == nums[--j]); // 跳过重复的元素
  19. }
  20. }
  21. }
  22. return res; // 返回结果列表
  23. }
  24. }

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/知新_RL/article/detail/146230
推荐阅读
相关标签
  

闽ICP备14008679号