for(int i=1;i<prices.size();i++){
dp[i][0]=max(dp[i-1][0], dp[i-1][1]+prices[i]);
dp[i][1]=max(dp[i-1][1],dp[i-1][0]-prices[i]);
}
最后代码如下:
class Solution {
public:
int maxProfit(vector<int>& prices) {
vector<vector<int>> dp(prices.size(),vector<int>(2,0));
dp[0][0]=0;
dp[0][1]=-prices[0];
for(int i=1;i<prices.size();i++){
dp[i][0]=max(dp[i-1][0], dp[i-1][1]+prices[i]);
dp[i][1]=max(dp[i-1][1],dp[i-1][0]-prices[i]);
}
return dp[prices.size()-1][0];
}
};
相当于分割字符串,而且要返回的是所有的分割方法
那就是回溯了
分割问题可以使用回溯搜索法把所有可能性搜出来
vector<string> result;
void backtracking(string& s, int startIndex,int pointNum)
if(pointNum==3)
{
if(isValid(s,startIndex,s.size()-1))
result.push_back(s);
}
for(int i=startIndex;i<s.size();i++)
{
if(isValid(s,startIndex,i)){
s.insert(s.begin()+i+1,'.');
pointNum++;
backtracking(s,i+2,pointNum);
pointNum--;
s.erase(s.begin()+i+1);
}else break;
接下来写一下如何判断字符串合法
有效 IP 地址 正好由四个整数(每个整数位于 0 到 255 之间组成,且不能含有前导 0)
那就是s[start]=='0’且start!=end,false
s[i] > ‘9’ || s[i] < ‘0’ false
num>255 false
bool isValid(string s,int start, int end)
{
if(s[start]=='0'&& start != end)
return false;
int num=0;
for(int i=start;i<=end;i++){
if(s[i] > '9' || s[i] < '0')
return false;
num = num * 10 + (s[i] - '0');
if (num > 255) { // 如果大于255了不合法
return false;
}
}
return true;
}
不过还存在另一种不合法的情况
当s="101023"时,我的代码输出了[“1.0.10.23”,“1.0.102.3”,“10.1.0.23”,“10.10.2.3”,“10.10.23.”,“10.102.3.”,“101.0.2.3”,“101.0.23.”]
而预期结果是[“1.0.10.23”,“1.0.102.3”,“10.1.0.23”,“10.10.2.3”,“10.10.23.”,“10.102.3.”,“101.0.2.3”,“101.0.23.”]
可以看到我的代码在字符串结尾加了分割
这是因为回溯的时候,i+2有可能大于s.size()
所以要判定一下start和end的大小
bool isValid(string s,int start, int end)
{
if(start>end)
return false;
if(s[start]=='0'&& start != end)
return false;
int num=0;
for(int i=start;i<=end;i++){
if(s[i] > '9' || s[i] < '0')
return false;
num = num * 10 + (s[i] - '0');
if (num > 255) { // 如果大于255了不合法
return false;
}
}
return true;
}
整体代码:
class Solution {
public:
bool isValid(string s,int start, int end)
{
if (start > end) {
return false;
}
if(s[start]=='0'&& start != end)
return false;
int num=0;
for(int i=start;i<=end;i++){
if(s[i] > '9' || s[i] < '0')
return false;
num = num * 10 + (s[i] - '0');
if (num > 255) { // 如果大于255了不合法
return false;
}
}
return true;
}
vector<string> result;
void backtracking(string& s, int startIndex, int pointNum) {
if (pointNum == 3) {
if (isValid(s, startIndex, s.size() - 1))
result.push_back(s);
return;
}
for (int i = startIndex; i < s.size(); i++) {
if (isValid(s, startIndex, i)) {
s.insert(s.begin() + i + 1, '.');
pointNum++;
backtracking(s, i + 2, pointNum);
pointNum--;
s.erase(s.begin() + i + 1);
} else {
break;
}
}
}
vector<string> restoreIpAddresses(string s) {
backtracking(s,0,0);
return result;
}
};
要返回满足题意的二叉搜索树种类数
同时呢,n个节点的二叉搜索树的构建可以由n-1个节点的二叉搜索树推导出来
所以是DP
确定dp数组(dp table)以及下标的含义
如图,头节点为1时,其左子树节点数量为0,右子树节点数量为2,节点数为0有1种构建方式,节点数为2有两种构建方式,所以头节点为1时,有1*2种构建方式
那么我们可以令dp[i]为当节点数为i时,有几种不同的构建方式
确定递推公式
dp[i]+=dp[j-1]*dp[i-j],j-1 为j为头结点左子树节点数量,i-j 为以j为头结点右子树节点数量
节点数为0有1种构建方式
dp[0]=1;
for(int i=1;i<=n;i++)
for(int j=1;j<=i;j++)
dp[i]+=dp[j-1]*dp[i-j];
最后代码如下:
class Solution {
public:
int numTrees(int n) {
vector<int> dp(n+1,0);
dp[0]=1;
for(int i=1;i<=n;i++)
for(int j=1;j<=i;j++)
dp[i]+=dp[j-1]*dp[i-j];
return dp[n];
}
};
这道题要返回所有的二叉搜索树了,那就是回溯了
涉及到树,后序遍历
vector<TreeNode*> backtracking(int left,int right)
if(left>right)
{
ans.push_back(nullptr);
return ans;
}
vector<TreeNode*> left_nodes=backtracking(left,i-1);
vector<TreeNode*> right_nodes=backtracking(i+1,right);
i左边的序列可以作为左子树结点,且左儿子可能有多个,所以有vector
i右边的序列可以作为右子树结点,同上所以有vector
因此,产生的以当前i为根结点的子树有left_nodes.size() * right_nodes.size()个,遍历每种情况,即可生成以i为根节点的子树序列;
for(TreeNode* left_node:left_nodes)
for(TreeNode* right_node:right_nodes)
{
TreeNode* tmp=new TreeNode(i);
tmp->left=left_node;
tmp->right=right_node;
ans.push_back(tmp);
}
即:
for(int i=left;i<=right;i++){
vector<TreeNode*> left_nodes=backtracking(left,i-1);
vector<TreeNode*> right_nodes=backtracking(i+1,right);
for(TreeNode* left_node:left_nodes)
for(TreeNode* right_node:right_nodes)
{
TreeNode* tmp=new TreeNode(i);
tmp->left=left_node;
tmp->right=right_node;
ans.push_back(tmp);
}
}
整理得到整个代码:
class Solution {
public:
vector<TreeNode*> backtracking(int left,int right){
vector<TreeNode *> ans;
if(left>right)
{
ans.push_back(nullptr);
return ans;
}
for(int i=left;i<=right;i++){
vector<TreeNode*> left_nodes=backtracking(left,i-1);
vector<TreeNode*> right_nodes=backtracking(i+1,right);
for(TreeNode* left_node:left_nodes)
for(TreeNode* right_node:right_nodes)
{
TreeNode* tmp=new TreeNode(i);
tmp->left=left_node;
tmp->right=right_node;
ans.push_back(tmp);
}
}
return ans;
}
vector<TreeNode*> generateTrees(int n) {
return backtracking(1,n);
}
};