LeetCode11: Container With Most Water

原题目:
Given n non-negative integers a1, a2, ..., an, where each represents a point at coordinate (i, ai). n vertical lines are drawn such that the two endpoints of line i is at (i, ai) and (i, 0). Find two lines, which together with x-axis forms a container, such that the container contains the most water.
Note: You may not slant the container.

在X轴有很多垂直的线段,线段长度分别为a1,a2,a3......an,在任意两条线和X轴之间形成一个面积,求能够形成的最大面积。
这里面有一个短板的问题,对于任意两条线ia,ib我们可以得出一个公式S = Math.abs((ia-ib))*Math.min(height[ia],height[ib]).

算法分析:
算法1:遍历法
用两层for循环,从头开始依次向后扫面,每次扫描到的两条线求面积,通过比较求出最大面积。缺点:双层for循环的时间复杂度为O(n^2),在LeetCode提交时因为超时而无法通过。

算法2:
从前后两边同时搜索,短板的那一侧往里走,以为往里走,代表宽度减小,那么宽度减小的时候,只有遇上了更高的高度才能组成更大的面积。所以依次从两侧往里走,直到两条线相遇。
 
算法3: 6的飞起!
设置两个指针i, j, 一头一尾, 相向而行. 假设i指向的挡板较低, j指向的挡板较高(height[i] < height[j]).
下一步移动哪个指针?
-- 若移动j, 无论height[j-1]是何种高度, 形成的面积都小于之前的面积.
-- 若移动i, 若height[i+1] <= height[i], 面积一定缩小; 但若height[i+1] > height[i], 面积则有可能增大.
综上, 应该移动指向较低挡板的那个指针.


LeetCode提交源码:
算法2:
   
   
  1. public int maxArea(int[] height) {
  2. if(height == null || height.length < 2){
  3. return 0;
  4. }
  5. int maxarea = 0;
  6. int left = 0;
  7. int right = height.length-1;
  8. while(left < right){
  9. maxarea = Math.max(maxarea, (right - left) * Math.min(height[left], height[right]));
  10. if(height[left] < height[right]){
  11. left++;
  12. }
  13. else{
  14. right--;
  15. }
  16. }
  17. return maxarea;
  18. }
 

算法3:
   
   
  1. public int maxArea(int[] height) {
  2. if (height==null || height.length==0) { return 0; }
  3. int max = 0;
  4. int i = 0, j = height.length-1;
  5. while (i < j) {
  6. max = Math.max(max, (j-i) * Math.min(height[i], height[j]));
  7. if (height[i] < height[j]) { // should move i
  8. int k; for (k=i+1; k<j && height[k]<=height[i]; ++k) {}
  9. i = k;
  10. } else { // should move j
  11. int k; for (k=j-1; k>i && height[k]<=height[j]; --k) {}
  12. j = k;
  13. }
  14. }
  15. return max;
  16. }

 
完整运行程序:

   
   
  1. /**************************************************************
  2. * Copyright (c) 2016
  3. * All rights reserved.
  4. * 版 本 号:v1.0
  5. * 题目描述: Container With Most Water
  6. * Given n non-negative integers a1, a2, ..., an, where each represents a point at coordinate (i, ai).
  7. * n vertical lines are drawn such that the two endpoints of line i is at (i, ai) and (i, 0).
  8. * Find two lines, which together with x-axis forms a container, such that the container contains the most water.
  9. * Note: You may not slant the container.
  10. * 输入描述:请输入整数一个数组,以空格隔开
  11. * 5 9 6 37 5 8 2 6 3 9
  12. * 程序输出:算法2:最大面积是:
  13. * 72
  14. * 算法3:最大面积是:
  15. * 72
  16. * 问题分析:双层for循环,时间复杂度较大
  17. * 算法描述:算法1:遍历法,用两层for循环,从头开始依次向后扫面,每次扫描到的两条线求面积,
  18. * 通过比较求出最大面积。缺点:双层for循环的时间复杂度为O(n^2),在LeetCode提交时因为超时而无法通过。
  19. * 算法2:
  20. * 从前后两边同时搜索,短板的那一侧往里走,以为往里走,代表宽度减小,那么宽度减小的时候,
  21. * 只有遇上了更高的高度才能组成更大的面积。所以依次从两侧往里走,直到两条线相遇。
  22. * 算法3: 6的飞起!
  23. * 设置两个指针i, j, 一头一尾, 相向而行. 假设i指向的挡板较低, j指向的挡板较高(height[i] < height[j]).
  24. * 下一步移动哪个指针?
  25. * -- 若移动j, 无论height[j-1]是何种高度, 形成的面积都小于之前的面积.
  26. * -- 若移动i, 若height[i+1] <= height[i], 面积一定缩小; 但若height[i+1] > height[i], 面积则有可能增大.
  27. * 综上, 应该移动指向较低挡板的那个指针.————摘自LeetCode大神
  28. * 完成时间:2016-11-24
  29. ***************************************************************/
  30. package org.GuoGuoFighting.LeetCode011;
  31. import java.util.Scanner;
  32. /*
  33. * 算法1:双层for循环,时间复杂度较大,对于大量数据输入会导致超出时间限制,
  34. */
  35. class SolutionMethod1{
  36. public int maxArea(int[] height){
  37. if(height == null || height.length < 0){
  38. return -1;
  39. }
  40. if(height.length == 1){
  41. return 0;
  42. }
  43. int sqrt = 0;
  44. // int i = 1;
  45. // int j = 2;
  46. //int reuslt = 0;
  47. int tmp;
  48. for(int i = 1; i <= height.length; i++){
  49. for(int j = i + 1;j <= height.length; j++){
  50. if(height[j] > height[i]){
  51. tmp = Math.abs(j-i)*height[i];
  52. //System.out.println("tmp= " + tmp + ",i = " + i + ",j=" +j);
  53. if(sqrt < tmp){
  54. sqrt = tmp;
  55. }
  56. }
  57. // tmp= Math.abs(j-i)*Math.min(height[i-1],height[j-1]);
  58. }
  59. }
  60. return sqrt;
  61. }
  62. }
  63. class SolutionMethod2{
  64. public int maxArea(int[] height) {
  65. if(height == null || height.length < 2){
  66. return 0;
  67. }
  68. int maxarea = 0;
  69. int left = 0;
  70. int right = height.length-1;
  71. while(left < right){
  72. maxarea = Math.max(maxarea, (right - left) * Math.min(height[left], height[right]));
  73. if(height[left] < height[right]){
  74. left++;
  75. }
  76. else{
  77. right--;
  78. }
  79. }
  80. return maxarea;
  81. }
  82. }
  83. /*算法3:6的飞起啊!
  84. 设置两个指针i, j, 一头一尾, 相向而行. 假设i指向的挡板较低, j指向的挡板较高(height[i] < height[j]).
  85. 下一步移动哪个指针?
  86. -- 若移动j, 无论height[j-1]是何种高度, 形成的面积都小于之前的面积.
  87. -- 若移动i, 若height[i+1] <= height[i], 面积一定缩小; 但若height[i+1] > height[i], 面积则有可能增大.
  88. 综上, 应该移动指向较低挡板的那个指针.
  89. */
  90. class SolutionMethod3 {
  91. public int maxArea(int[] height) {
  92. if (height==null || height.length==0) { return 0; }
  93. int max = 0;
  94. int i = 0, j = height.length-1;
  95. while (i < j) {
  96. max = Math.max(max, (j-i) * Math.min(height[i], height[j]));
  97. if (height[i] < height[j]) { // should move i
  98. int k; for (k=i+1; k<j && height[k]<=height[i]; ++k) {}
  99. i = k;
  100. } else { // should move j
  101. int k; for (k=j-1; k>i && height[k]<=height[j]; --k) {}
  102. j = k;
  103. }
  104. }
  105. return max;
  106. }
  107. }
  108. public class ContainerWithMostWater {
  109. public static void main(String[] args){
  110. Scanner scanner = new Scanner(System.in);
  111. System.out.println("请输入整数一个数组,以空格隔开");
  112. String str = scanner.nextLine();
  113. String[] tmp = str.split(" ");
  114. int[] array = new int[tmp.length];
  115. for(int i = 0;i < array.length; i++){
  116. array[i] = Integer.parseInt(tmp[i]);
  117. }
  118. scanner.close();
  119. // SolutionMethod1 solution1 = new SolutionMethod1();
  120. // System.out.println("算法1:最大面积是:");
  121. // System.out.println(solution1.maxArea(array));
  122. SolutionMethod2 solution2 = new SolutionMethod2();
  123. System.out.println("算法2:最大面积是:");
  124. System.out.println(solution2.maxArea(array));
  125. SolutionMethod3 solution3 = new SolutionMethod3();
  126. System.out.println("算法3:最大面积是:");
  127. System.out.println(solution3.maxArea(array));
  128. }
  129. }

程序运行结果:
 


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值