给你 n 个非负整数 a1,a2,...,an,每个数代表坐标中的一个点 (i, ai) 。在坐标内画 n 条垂直线,垂直线 i 的两个端点分别为 (i, ai) 和 (i, 0)。找出其中的两条线,使得它们与 x 轴共同构成的容器可以容纳最多的水。
说明:你不能倾斜容器,且 n 的值至少为 2。
图中垂直线代表输入数组 [1,8,6,2,5,4,8,3,7]。在此情况下,容器能够容纳水(表示为蓝色部分)的最大值为 49。
示例:
输入:[1,8,6,2,5,4,8,3,7]
输出:49
思路分析
复杂度分析:
N
表示数组的长度class Solution {
public int maxArea(int[] height) {
if (height.length<2) {
return 0;
}
int max = 0;
for (int i =0;i
思路:
算法流程: 设置双指针 i,j分别位于容器壁两端,根据规则移动指针(后续说明),并且更新面积最大值 res,直到 i == j 时返回 res。
指针移动规则与证明: 每次选定围成水槽两板高度 h[i],h[j]中的短板,向中间收窄 1 格。以下证明:
设每一状态下水槽面积为 S(i, j),(0 <= i < j < n),由于水槽的实际高度由两板中的短板决定,则可得面积公式 S(i, j) = min(h[i], h[j]) × (j - i)。
在每一个状态下,无论长板或短板收窄 1 格,都会导致水槽 底边宽度 −1:
若向内移动短板,水槽的短板 min(h[i], h[j])可能变大,因此水槽面积 S(i, j) 可能增大。
若向内移动长板,水槽的短板 min(h[i], h[j]) 不变或变小,下个水槽的面积一定小于当前水槽面积。
因此,向内收窄短板可以获取面积最大值。
时间复杂度 O(N),双指针遍历一次底边宽度 N 。
空间复杂度 O(1),指针使用常数额外空间。
代码:
class Solution {
public int maxArea(int[] height) {//双指针解法
int maxArea= 0;
for (int i =0, j = height.length -1 ; i < j ;) {
int minHeigth = height[i] < height[j] ? height[i ++] : height[j --];//巧妙的 移动指针
int area = minHeigth * (j - i +1);
maxArea = Math.max(maxArea,area);
}
return maxArea;
}
}
给定一个数组 nums
,编写一个函数将所有 0
移动到数组的末尾,同时保持非零元素的相对顺序。
示例:
输入:[0,1,0,3,12]
输出:[1,3,12,0,0]
说明:
解题思路
class Solution {
public void moveZeroes(int[] nums) {
int index = 0;
for(int num:nums){
if(num!=0){
nums[index++]=num;
}
}
while(index
双指针交换数据
class Solution {
public void moveZeroes(int[] nums) {
int j = 0 ;
for (int i= 0; i < nums.length; i ++) {
if (nums[i] != 0) {
if (i != j) {
int num = nums[j];
nums[j] = nums[i];
nums[i] = num;
}
j ++ ;
}
}
}
}
假设你正在爬楼梯。需要 n 阶你才能到达楼顶。
每次你可以爬 1 或 2 个台阶。你有多少种不同的方法可以爬到楼顶呢?
注意:给定 n 是一个正整数。
示例 1:
输入: 2
输出: 2
解释: 有两种方法可以爬到楼顶。
1. 1 阶 + 1 阶
2. 2 阶
示例 2:
输入: 3
输出: 3
解释: 有三种方法可以爬到楼顶。
1. 1 阶 + 1 阶 + 1 阶
2. 1 阶 + 2 阶
3. 2 阶 + 1 阶
算法
不难发现,这个问题可以被分解为一些包含最优子结构的子问题,即它的最优解可以从其子问题的最优解来有效地构建,我们可以使用动态规划来解决这一问题。
第 ii 阶可以由以下两种方法得到:
在第 (i-1)阶后向上爬一阶。
在第 (i-2) 阶后向上爬 2阶。
所以到达第 ii 阶的方法总数就是到第 (i-1) 阶和第 (i-2)阶的方法数之和。
令 dp[i]dp[i] 表示能到达第 ii 阶的方法总数:
dp[i]=dp[i-1]+dp[i-2]
class Solution {
public int climbStairs(int n) {
int[] dp = new int[n + 2];
dp[1] = 1;
dp[2] = 2;
for (int i =3 ; i <= n ; i ++) {
dp[i] =dp[i- 1] + dp[i -2];
}
return dp[n];
}
}
算法
在上述方法中,我们使用 dpdp 数组,其中 dp[i]=dp[i-1]+dp[i-2]。可以很容易通过分析得出 dp[i] 其实就是第 i 个斐波那契数。
Fib(n)=Fib(n-1)+Fib(n-2)
class Solution {
public int climbStairs(int n) { //斐波那契数
if (n==1) return 1;
if (n==2) return 2;
int f1 =1 ,f2 = 2 ,f3 =3;
for (int i =3; i <=n ; i ++ ) {
f3 = f2 + f1;
f1 =f2;
f2 = f3;
}
return f3;
}
}