題目: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.
就是說,x軸上在1,2,...,n點上有許多垂直的線段,長度依次是a1, a2, ..., an。找出兩條線段,使他們和x抽圍成的面積最大。面積公式是 Min(ai, aj) X |j - i|
解法1:大家都能想到的,窮舉所有(i,j)可能,找一個最大的。
1 //O(n^2) 2 public static int maxArea(int[] height) { 3 // Start typing your Java solution below 4 // DO NOT write main() function 5 int maxArea = 0; 6 for(int i = 1; i < height.length; i++){ 7 if(height[i] == 0)continue; 8 for(int j = 0; j < i; j++) { 9 int area = area(height,i,j); 10 if(area > maxArea) { 11 maxArea = area; 12 } 13 } 14 } 15 return maxArea; 16 }
不過這樣的話無法通過leetcode大集合。
解法2:可以對解法1中的第二個循環中的j做預先判斷從而跳過某些情況。在我們檢查比i小的各個j時,計算面積的短板不會超過ai本身。平均到距離上,j不會在一定距離上靠近i。
1 public static int maxArea(int[] height) { 2 // Start typing your Java solution below 3 // DO NOT write main() function 4 int maxArea = 0; 5 for(int i = 1; i < height.length; i++){ 6 if(height[i] == 0)continue; 7 int maxPossibleIdx = i - maxArea/height[i]; 8 for(int j = 0; j < i && j <= maxPossibleIdx; j++) { 9 int area = area(height,i,j); 10 if(area > maxArea) { 11 maxArea = area; 12 } 13 } 14 } 15 return maxArea; 16 }
這個方法能夠通過大集合。
解法3: O(n)的復雜度。保持兩個指針i,j;分別指向長度數組的首尾。如果ai 小於aj,則移動i向后(i++)。反之,移動j向前(j--)。如果當前的area大於了所記錄的area,替換之。這個想法的基礎是,如果i的長度小於j,無論如何移動j,短板在i,不可能找到比當前記錄的area更大的值了,只能通過移動i來找到新的可能的更大面積。
1 public static int maxArea(int[] height){ 2 int maxArea = 0; 3 int i = 0; 4 int j = height.length - 1; 5 if(j <=0)return 0; 6 while(i < j) { 7 int area = area(height, i, j); 8 if(height[i] < height[j]){ 9 i++; 10 11 }else { 12 j--; 13 } 14 if(area > maxArea) maxArea = area; 15 } 16 return maxArea; 17 }
