盛水最多的容器
给你 n 个非负整数 a1,a2,…,an,每个数代表坐标中的一个点 (i, ai) 。在坐标内画 n 条垂直线,垂直线 i 的两个端点分别为 (i, ai) 和 (i, 0) 。找出其中的两条线,使得它们与 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
示例 3:
输入:height = [4,3,2,1,4]
输出:16
示例 4:
输入:height = [1,2,1]
输出:2
提示:
n = height.length
2 <= n <= 3 * 104
0 <= height[i] <= 3 * 104
java解决
1.遍历法:
两个循环遍历分别计算每一个柱子之间的容量
找到最大的容量
缺点:时间复杂度高
class Solution {
public int maxArea(int[] height) {
int width ;
int minHeight;
int maxValue=0;
for(int i = 0;i<height.length;i++){
for(int j = i+1;j<height.length;j++){
if(height[i]<height[j])
minHeight = height[i];
else
minHeight = height[j];
width = j - i;
if(maxValue<(width*minHeight)){
maxValue = width*minHeight;
}
}
}
return maxValue;
}
}
//缺点: 时间复杂度高
2.双指针遍历
上面的遍历其实也类似双指针,但是for循环的嵌套相当于固定一个指针,移动另一个指针,所以要找到最大的就必须全部遍历完毕,显然有很多是不用去遍历的,所以双指针可以减少遍历的次数.
思考一下:
按照上面的图来讲: 首先两个指针 i 和 j 分别在 0 和 length - 1 处 时,这个时候容器的容量等于: i 和 j 之间的距离 (j - i)*他们中最低的柱子. 面积等于 1 * 8 = 8
这时两个指针就要发生移动, 可以想象一下, 定一动一:
1. 定小( i )动大( j ) : 这时不论 j 移动到任何位置, 他们中的高度始终时最低的 i = 1 ; 所以不论 j 移动到任何地方,面积都不会比 8 要大;
2. 定大( j )动小( i ): 这时当指针 i 向后移动后,如果 i 找到了比原来的 i 处的值更大的数 , 那么容器的容量( 面积 )就会不一样, 这样才有可能超过第一次的面积;
3. 同时移动: 同时移动两个指针,虽然面积也有可能会超过第一次面积,但是,这样移动有可能会漏掉很多的面积,如果碰巧漏掉了最大值,结论就会时错误的.
所以,上述结论不难看出, 我们只需要定大的柱子, 移动值稍微小点的柱子, 那么就可以找到所有的更大的面积;
class Solution {
public int maxArea(int[] height) {
int maxValue = 0;
int i = 0;
int j = height.length - 1;
while (i < j) {
int area = (j - i) * Math.min(height[i], height[j]);
maxValue = Math.max(maxValue, area);
if (height[i] < height[j])
i++;
else
j--;
}
return maxValue;
}
}
python方案
双指针:
class Solution:
def maxArea(self, height: List[int]) -> int:
i = 0
j = len(height)-1
maxValue = 0
while(i<j):
area = min(height[i],height[j])*(j - i)
maxValue = max(maxValue,area)
if(height[i]<height[j]):
i+=1
else:
j-=1
return maxValue
整数转罗马数字
java解决
罗马数字有自身的规则:
{1000, 900, 500, 400, 100, 90, 50, 40, 10, 9, 5, 4, 1}
{"M","CM","D","CD","C","XC","L","XL","X","IX","V","IV","I"}
按照上面两个数组中的元素对应: 1000 就是 M , 999 就是 CMXCIX,
整体规则其实并不明朗,因为 1 -> I , 2 -> II 3 ->III , 4 却不是 IIII 而是 IV
所以,把一些特殊的加进去即可,总体上满足,有大的优先大的:
class Solution {
int[] values = {1000, 900, 500, 400, 100, 90, 50, 40, 10, 9, 5, 4, 1};
String[] flag = {"M","CM","D","CD","C","XC","L","XL","X","IX","V","IV","I"};
public String intToRoman(int num) {
StringBuilder sb = new StringBuilder();
for (int i = 0; i < values.length && num >= 0; i++) {
while (values[i] <= num) {
num -= values[i];
sb.append(flag[i]);
}
}
return sb.toString();
}
}
python
同上,不过,python有dict字典可以使用,所以方便我们建立哈希表:
class Solution:
def intToRoman(self, num: int) -> str:
hashmap = {1000:'M', 900:'CM', 500:'D', 400:'CD', 100:'C', 90:'XC', 50:'L', 40:'XL', 10:'X', 9:'IX', 5:'V', 4:'IV', 1:'I'}
s1 = ''
for key in hashmap:
if num // key != 0:
count = num // key
s1 += hashmap[key] * count
num %= key
return s1