11. 盛最多水的容器
给定一个长度为 n 的整数数组 height 。有 n 条垂线,第 i 条线的两个端点是 (i, 0) 和 (i, height[i]) 。
找出其中的两条线,使得它们与 x 轴共同构成的容器可以容纳最多的水。
返回容器可以储存的最大水量。
说明:你不能倾斜容器。
来源:力扣(LeetCode)
链接:https://leetcode.cn/problems/container-with-most-water
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
思路:
首先想到的是遍历数组,逐一进行计算获取最大值。时间复杂度
O
(
n
!
)
O(n!)
O(n!),时间超限。
官方给出双指针的解法,理解之后进行了使用。
双指针证明:
设
x
x
x为指向容器左边的指针,
y
y
y为指向容器右边的指针,
t
t
t为
x
x
x,
y
y
y之间的距离,则容器的容量为
m
i
n
(
x
,
y
)
∗
t
min(x,y)*t
min(x,y)∗t,
m
i
n
(
x
,
y
)
min(x,y)
min(x,y)指
x
x
x与
y
y
y之间的最小值。双指针算法核心在于:每次计算结束,移动值较小的那个指针,因此需证明为什么不能任意移动指针。
采用假设法:
假设
x
<
y
x<y
x<y(即
m
i
n
(
x
,
y
)
=
x
,
m
i
n
(
x
,
y
)
∗
t
=
x
∗
t
min(x,y)=x,min(x,y)*t=x*t
min(x,y)=x,min(x,y)∗t=x∗t),若固定
x
x
x,移动
y
y
y,则有
m
i
n
(
x
,
y
i
)
∗
t
i
min(x, y_{i})*t_{i}
min(x,yi)∗ti,
t
i
<
t
t_{i}<t
ti<t,因此:
①当
y
i
<
y
y_{i}<y
yi<y时,若
y
i
<
x
y_{i}<x
yi<x,则
m
i
n
(
x
,
y
i
)
<
m
i
n
(
x
,
y
)
min(x, y_{i})<min(x,y)
min(x,yi)<min(x,y),故
m
i
n
(
x
,
y
i
)
∗
t
i
<
m
i
n
(
x
,
y
)
∗
t
min(x, y_{i})*t_{i}<min(x,y)*t
min(x,yi)∗ti<min(x,y)∗t;
若
y
i
>
x
y_{i}>x
yi>x,则
m
i
n
(
x
,
y
i
)
=
m
i
n
(
x
,
y
)
=
x
min(x, y_{i})=min(x,y)=x
min(x,yi)=min(x,y)=x,又
t
i
<
t
t_{i}<t
ti<t,故
m
i
n
(
x
,
y
i
)
∗
t
i
<
m
i
n
(
x
,
y
)
∗
t
min(x, y_{i})*t_{i}<min(x,y)*t
min(x,yi)∗ti<min(x,y)∗t
②当
y
i
>
=
y
y_{i}>=y
yi>=y时,
m
i
n
(
x
,
y
i
)
=
m
i
n
(
x
,
y
)
=
x
min(x, y_{i})=min(x,y)=x
min(x,yi)=min(x,y)=x,又
t
i
<
t
t_{i}<t
ti<t,故
m
i
n
(
x
,
y
i
)
∗
t
i
<
m
i
n
(
x
,
y
)
∗
t
min(x, y_{i})*t_{i}<min(x,y)*t
min(x,yi)∗ti<min(x,y)∗t;
因此当固定住值较小的那个指针时,无论怎样移动另一个指针,都不会存在大于
m
i
n
(
x
,
y
)
∗
t
min(x,y)*t
min(x,y)∗t的值。同理可证移动左指针。
代码:
class Solution {
public:
int maxArea(vector<int>& height) {
int result = 0;
for(int i=0, j=height.size()-1; i<j;){
int temp = 0;
if(height[i] < height[j]){
temp = height[i] * (j - i);
i++;
} else {
temp = height[j] * (j - i);
j--;
}
if(temp > result){
result = temp;
}
}
return result;
}
};
12. 整数转罗马数字
罗马数字包含以下七种字符: I, V, X, L,C,D 和 M。
字符 | 数值 |
---|---|
I | 1 |
V | 5 |
X | 10 |
L | 50 |
C | 100 |
D | 500 |
M | 1000 |
例如, 罗马数字 2 写做 II ,即为两个并列的 1。12 写做 XII ,即为 X + II 。 27 写做 XXVII, 即为 XX + V + II 。
通常情况下,罗马数字中小的数字在大的数字的右边。但也存在特例,例如 4 不写做 IIII,而是 IV。数字 1 在数字 5 的左边,所表示的数等于大数 5 减小数 1 得到的数值 4 。同样地,数字 9 表示为 IX。这个特殊的规则只适用于以下六种情况:
I 可以放在 V (5) 和 X (10) 的左边,来表示 4 和 9。
X 可以放在 L (50) 和 C (100) 的左边,来表示 40 和 90。
C 可以放在 D (500) 和 M (1000) 的左边,来表示 400 和 900。
给你一个整数,将其转为罗马数字。
来源:力扣(LeetCode)
链接:https://leetcode.cn/problems/integer-to-roman
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
class Solution {
public:
string intToRoman(int num) {
string TH[4] = {"", "M", "MM", "MMM"};
string HU[10] = {"", "C", "CC", "CCC", "CD", "D", "DC", "DCC", "DCCC", "CM"};
string DE[10] = {"", "X", "XX", "XXX", "XL", "L", "LX", "LXX", "LXXX", "XC"};
string UN[10] = {"", "I", "II", "III", "IV", "V", "VI", "VII", "VIII", "IX"};
int th = num / 1000;
num = num % 1000;
int hu = num / 100;
num = num % 100;
int de = num / 10;
num = num % 10;
int un = num;
return TH[th]+HU[hu]+DE[de]+UN[un];
}
};