本篇是LeetCode DP类别的中级(Medium(前四) + Hard)题目:
A robot is located at the top-left corner of a m x n grid (marked 'Start' in the diagram below).
The robot can only move either down or right at any point in time. The robot is trying to reach the bottom-right corner of the grid (marked 'Finish' in the diagram below).
How many possible unique paths are there?
Note: m and n will be at most 100. * pathNum[i][j]表示(0,0)到(i,j)的不同路径数目,递推关系如下
pathNum[i][0] = 1;
pathNum[0][i] = 1;
pathNum[i][j] = pathNum[i - 1][j] + pathNum[i][j - 1];
int uniquePaths(int m, int n)
{
vector<vector<int>> pathNum(m, vector<int>(n));
for (int i = 0; i < m; i++)
{
pathNum[i][0] = 1;
}
for (int i = 0; i < n; i++)
{
pathNum[0][i] = 1;
}
for (int i = 1; i < m; i++)
{
for (int j = 1; j < n; j++)
{
pathNum[i][j] = pathNum[i - 1][j] + pathNum[i][j - 1];
}
}
return pathNum[m - 1][n - 1];
}
Follow up for "Unique Paths":
Now consider if some obstacles are added to the grids. How many unique paths would there be?
An obstacle and empty space is marked as 1 and 0 respectively in the grid.
For example,
There is one obstacle in the middle of a 3x3 grid as illustrated below.
[
[0,0,0],
[0,1,0],
[0,0,0]
]
The total number of unique paths is 2.
Note: m and n will be at most 100.
pathNum[0][0] = obstacleGrid[0][0] == 0? 1:0;
pathNum[0][i] = obstacleGrid[0][i] == 0? pathNum[0][i-1]:0;
pathNum[i][0] = obstacleGrid[i][0] == 0? pathNum[i-1][0]:0;
pathNum[i][j] = obstacleGrid[i][j] == 0? pathNum[i - 1][j] + pathNum[i][j - 1] : 0;
int uniquePathsWithObstacles(vector<vector<int> > &obstacleGrid)
{
int m = obstacleGrid.size();
int n = obstacleGrid[0].size();
vector<vector<int>> pathNum(m, vector<int>(n, 0));
if (obstacleGrid[0][0] == 0){
pathNum[0][0] = 1;
}
for (int i = 1; i < m; i++){
if (obstacleGrid[i][0] != 1){
pathNum[i][0] = pathNum[i - 1][0];
}
}
for (int i = 1; i < n; i++){
if (obstacleGrid[0][i] != 1){
pathNum[0][i] = pathNum[0][i - 1];
}
}
//other grid
for (int i = 1; i < m; i++){
for (int j = 1; j < n; j++){
if (obstacleGrid[i][j] != 1){
pathNum[i][j] = pathNum[i - 1][j] + pathNum[i][j - 1];
}
}
}
return pathNum[m - 1][n - 1];
}
Given n, how many structurally unique BST's (binary search trees) that store values 1...n?
For example,
Given n = 3, there are a total of 5 unique BST's.
1 3 3 2 1
\ / / / \ \
3 2 1 1 3 2
/ / \ \
2 1 2 3
int numTrees(int n)
{
assert(n > 0);
vector<int> f(n + 1, 0);
f[0] = 1;
f[1] = 1;
for (int i = 2; i <= n; i++)
{//f(i)
for (int j = 1; j <= i; j++)
{//g(i,j)
f[i] += f[j - 1] * f[i - j];
}
}
return f[n];
}
Given n, generate all structurally unique BST's (binary search trees) that store values 1...n.
For example, Given n = 3, your program should return all 5 unique BST's shown below.
1 3 3 2 1
\ / / / \ \
3 2 1 1 3 2
/ / \ \
2 1 2 3
DFS方法构造BST
class Solution {
vector<TreeNode *> buildBST(int start, int end)
{
vector<TreeNode*> subtree;
if (start > end)
{
subtree.push_back(NULL);
return subtree;
}
if (start == end)
{
TreeNode *node = new TreeNode(start);
subtree.push_back(node);
return subtree;
}
for (int i = start; i <= end; i++)
{
TreeNode *root;
vector<TreeNode*> vleft = buildBST(start, i - 1);
vector<TreeNode*> vright = buildBST(i + 1, end);
for (int j = 0; j < vleft.size(); j++)
{
for (int k = 0; k < vright.size(); k++)
{
root = new TreeNode(i);
root->left = vleft[j];
root->right = vright[k];
subtree.push_back(root);
}
}
}
return subtree;
}
public:
vector<TreeNode *> generateTrees(int n)
{
return buildBST(1, n);
}
};
Given two words word1 and word2, find the minimum number of steps required to convert word1 to word2. (each operation is counted as 1 step.)
You have the following 3 operations permitted on a word:
a) Insert a character
b) Delete a character
c) Replace a character
这是动态规划的一个经典题目,下面用一个例子说明求解思路
一图胜千言,从word转换成world的步骤如下图所示:
int minDistance(string s1, string s2)
{
int m = s1.size();
int n = s2.size();
vector<vector<int> > dist(m + 1, vector<int>(n + 1, 0));
for (int i = 0; i <= m; i++)
{//delete
dist[i][0] = i;
}
for (int i = 0; i <= n; i++)
{//insert
dist[0][i] = i;
}
for (int i = 1; i <= m; i++)
{
for (int j = 1; j <= n; j++)
{
if (s1[i - 1] == s2[j - 1])
{
dist[i][j] = min(min(dist[i - 1][j], dist[i][j - 1]) + 1, dist[i - 1][j - 1]);
}
else
{
dist[i][j] = min(min(dist[i - 1][j], dist[i][j - 1]) + 1, dist[i - 1][j - 1] + 1);
}
}
}
return dist[m][n];
}
Given a string S and a string T, count the number of distinct subsequences of T in S.
A subsequence of a string is a new string which is formed from the original string by deleting some (can be none) of the characters without disturbing the relative positions of the remaining characters. (ie, "ACE" is a subsequence of "ABCDE" while "AEC" is not).
Here is an example:
S = "rabbbit", T = "rabbit"
Return 3.
它和Edit Distance很相似
int numDistinct(string S, string T)
{
int n = S.length();
int m = T.length();
if (m > n)
return 0;
vector<vector<int>> path(m + 1, vector<int>(n + 1, 0));
for (int k = 0; k <= n; k++)
path[0][k] = 1;
for (int j = 1; j <= n; j++)
{
for (int i = 1; i <= m; i++)
{
path[i][j] = path[i][j - 1] + (T[i - 1] == S[j - 1] ? path[i - 1][j - 1] : 0);
}
}
return path[m][n];
}
Say you have an array for which the ith element is the price of a given stock on day i.
Design an algorithm to find the maximum profit. You may complete at most two transactions.
Note: You may not engage in multiple transactions at the same time (ie, you must sell the stock before you buy again).
Best Time to Buy and Sell Stock最多交易一次,本题目多了一次交易,可以买卖2次,思路就是这个2,难点就是在两次交易不重叠的情况下获得最大收益:
int maxProfit(vector<int> &prices)
{
int n = prices.size();
if (n < 2){
return 0;
}
vector<int> g(n, 0);
vector<int> f(n, 0);
for (int i = 1, minP = prices[0]; i < n; i++){
minP = min(minP, prices[i]);
g[i] = max(g[i - 1], prices[i] - minP);
}
for (int i = n - 2, maxP = prices[n - 1]; i >= 0; i--){
maxP = max(maxP, prices[i]);
f[i] = max(f[i + 1], maxP - prices[i]);
}
int max_profit = 0;
for (int i = 0; i < n; i++){
if (max_profit < g[i] + f[i]){
max_profit = g[i] + f[i];
}
}
return max_profit;
}
Given a string containing just the characters '(' and ')', find the length of the longest valid (well-formed) parentheses substring.
For "(()", the longest valid parentheses substring is "()", which has length = 2.
Another example is ")()())", where the longest valid parentheses substring is "()()", which has length = 4.
Stack is used to stored the character.
If current character is '(', push into the stack. If current character is ')', Case 1: the stack is empty, reset previous result to zero. Here we renew a pointer to store the earliest index. Case 2: the stack is not empty, pop the top element. if the top element is '(' , (which means a () pair is found), then if the poped stack is empty, (which means the previous pairs should be added.), len = current pos - previous pos +1; If the poped stack is not empty, len = current pos- index of stack top element.
int longestValidParentheses(string s)
{
if (s.size() < 2){
return 0;
}
stack<int > sp;
int maxlen = 0;
int last = -1;
for (int i = 0; i < s.size(); i++){
if (s[i] == '('){
sp.push(i);
}
else{
if (sp.empty()){//not match
last = i;
}
else{
sp.pop();
if (sp.empty()){
maxlen = max(maxlen, i - last);
}
else{
maxlen = max(maxlen, i - sp.top());
}
}
}
}
return maxlen;
}