11. 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 and n is at least 2.
Solution:
使用两边向中间逼近的方式遍历,实际就是将普通的遍历方式将从前往后和从后往前结合了:
#include<iostream>
using namespace std;
int main(){
int a[10] = {1,2,3,4,5,6,7,8,9,10};
int count = 1;
int times = 0;
for(int i=0, t=9; i<t; count++){
if(count%2){//我选择了轮流固定第一个和最后一个的方式,但实际上每轮遍历时可以随意固定第一个或者最后一个
for(int j=i+1; j<=t; j++){
cout<<a[i]<<' '<<a[j]<<endl;
times++;
}
i++;
}else{
for(int j=i; j<t; j++){
cout<<a[j]<<' '<<a[t]<<endl;
times++;
}
t--;
}
}
cout<<times<<endl;
return 0;
}
在这一题中,使用这种遍历方式,对于两个端点中高度较小的一个,一定可以确定固定它时得到的一组面积中最大的情况是它和另一个端点得到的面积,因此内层循环就可以直接节省掉。Code:
class Solution {
public:
int maxArea(vector<int>& height) {
int start = 0;
int last = height.size()-1;
int maxArea = 0;
while(start<last){
int newArea = min(height[start], height[last])*(last-start);
if(newArea>maxArea){
maxArea = newArea;
}
if(height[start]>height[last])
last--;
else
start++;
}
return maxArea;
}
};
120. Triangle
Given a triangle, find the minimum path sum from top to bottom. Each step you may move to adjacent numbers on the row below.
For example, given the following triangle
[ [2], [3,4], [6,5,7], [4,1,8,3] ]
The minimum path sum from top to bottom is 11
(i.e., 2 + 3 + 5 + 1 =
11).
Note:
Bonus point if you are able to do this using only O(n) extra space, where n is the total number of rows in the triangle.
Solution: 动态规划,设状态为f(i; j),表示从从位置(i; j) 出发,路径的最小和,则状态转移方程为: f(i, j) = min{ f(i, j + 1), f(i + 1, j + 1)} + (i, j)
Code:
class Solution {
public:
int minimumTotal(vector<vector<int>>& triangle) {
//sum_n[i] = min(sum_n+1[i], sum_n+1[i+1]) + triangle[n][i]
vector<int> sum(triangle.back().begin(), triangle.back().end());
int n = sum.size()-1;
while(n>0){
for(int i=0; i<n; i++){
sum[i] = min(sum[i], sum[i+1]) + triangle[n-1][i];
}
n--;
}
return sum[0];
}
};
132. Palindrome Partitioning II
Given a string s, partition s such that every substring of the partition is a palindrome.
Return the minimum cuts needed for a palindrome partitioning of s.
For example, given s = "aab"
,
Return 1
since the palindrome partitioning ["aa","b"]
could
be produced using 1 cut.
Solution: 对于一个子序列,找到所有可能的(包含第一个字母的所有回文)第一个切割点,然后计算每个切割点得到的子序列的最小切割数+1即可得到全局的最小值。状态转移方程式为:f(i) = min{ f(j + 1) + 1}, i <= j < n。注意:判断一个子序列是否为回文串也需要使用动规,直接判断会超时,动态转移方程式为:P[i][j] = str[i] == str[j] && P[i+1][j-1]。
Code:
class Solution {
public:
int minCut(string s) {
const int n = s.size();
bool p[n][n];
fill_n(&p[0][0], n*n, false);
vector<int> cutNeeds(s.size()+1, INT_MAX);//(0)a(1)a(2)b(3)
cutNeeds.back() = -1;
for(int i=cutNeeds.size()-2; i>=0; i--){
for(int t=i; t<s.size(); t++){
if(i==t) p[i][t] = true;
else if(i+1==t) p[i][t] = s[i]==s[t];
else p[i][t] = (s[i]==s[t]) && p[i+1][t-1];
if(p[i][t]){
//s(i:t)是个回文
int newcut = cutNeeds[t+1]+1;
if(newcut<cutNeeds[i]) cutNeeds[i] = newcut;
}
}
}
return cutNeeds[0];
}
};