贪心算法(又称贪婪算法)是指,在对问题求解时,总是做出在当前看来是最好的选择。也就是说,不从整体最优上加以考虑,他所做出的是在某种意义上的局部最优解。
贪心算法不是对所有问题都能得到整体最优解,关键是贪心策略的选择,选择的贪心策略必须具备无后效性,即某个状态以前的过程不会影响以后的状态,只与当前状态有关。
给定一个整数数组 nums ,找到一个具有最大和的连续子数组(子数组最少包含一个元素),返回其最大和。
示例:
输入: [-2,1,-3,4,-1,2,1,-5,4],
输出: 6
解释: 连续子数组 [4,-1,2,1] 的和最大,为 6。
思路:依次遍历,遇到所有数都累加,结果为负时,重新累加。用一个max实时记录子数组的最大值。
int maxSubArray(vector<int>& nums) {
int sum=0,max=INT_MIN;
for(auto i : nums){
sum+=i;
max=sum>max?sum:max;
if(sum<0) sum=0;
}
return max;
}
今天的行为 | 今天结束后的statr | 今天结束后的profit |
---|---|---|
今天什么也不做,或买入又卖出、卖出又买入 | 不变 | 不变 |
若持股,则卖出 | 1-0 | 加上今天的股价 |
若不持股,则买入 | 0-1 | 减去今天的股价 |
class Solution {
private:
int days;//记录最大天数
int max = 0;//记录最大收益
public:
int maxProfit(vector<int>& prices) {
days = prices.size();
//初始条件:昨天结束时也就是第一天开始时,未持股、利润为0
//再去列举第一天的三种行为,所以day = 0
DFS(prices,0,0,0);
return max;
}
//参数:day表示天数,第一天day=0,prices[day]即是今天的股价
void DFS(vector<int>& prices,int day,bool state,int profit){
if(day == days) {//到最后一天了
max = profit>max?profit:max;
return;
}
//第day+1天有3种行为,每种行为都使得profit变化
DFS(prices,day+1,state,profit);
if(state){
DFS(prices,day+1,!state,profit+prices[day]);
}else{
DFS(prices,day+1,!state,profit-prices[day]);
}
}
};
class Solution {
private:
int max = 0;//记录最大收益
public:
int maxProfit(vector<int>& prices) {
int days = prices.size();
for(int day = 0;day<days-1;day++){
int diff = prices[day+1]-prices[day];
if(diff > 0){
max += diff;
}
}
return max;
}
};
/**
* Definition for a binary tree node.
*/
struct TreeNode {
int val;
TreeNode *left;
TreeNode *right;
TreeNode(int x) : val(x), left(NULL), right(NULL) {}
};
class Solution {
public:
vector<vector<int>> levelOrder(TreeNode *root)
{
vector<vector<int>> res;
if (!root)
return res;
queue<TreeNode *> queue;
TreeNode *node;
queue.push(root);
while (!queue.empty())
{
vector<int> level_res;
int size = queue.size();
for (int i = 0; i < size; i++)
{
node = queue.front();
queue.pop();
level_res.emplace_back(node->val);
if (node->left)
queue.push(node->left);
if (node->right)
queue.push(node->right);
}
res.push_back(level_res);
}
return res;
}
};
作者:24shi-01fen-_00_01
链接:https://leetcode-cn.com/problems/binary-tree-level-order-traversal/solution/bfsdie-dai-di-gui-by-24shi-01fen-_00_01/
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
class Solution {
public:
vector<vector<int>> levelOrder(TreeNode* root) {
vector<vector<int>> res;
helper(res,root,0);
return res;
}
void helper(vector<vector<int>>& res,TreeNode* node,int level){
if(!node) return ;
if(level>=res.size()){
vector<int> level_res;
res.emplace_back(level_res);
}
res[level].emplace_back(node->val);
if(node->left) helper(res,node->left,level+1);
if(node->right) helper(res,node->right,level+1);
}
};
作者:24shi-01fen-_00_01
链接:https://leetcode-cn.com/problems/binary-tree-level-order-traversal/solution/bfsdie-dai-di-gui-by-24shi-01fen-_00_01/
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
Given a binary tree and a sum, determine if the tree has a
root-to-leaf path such that adding up all the values along the path
equals the given sum.
class Solution {
public:
bool hasPathSum(TreeNode *node,int sum){
if(!node) return false;
if(!node->left&&!node->right){
if(node->val == sum) return true;
}
return hasPathSum(node->left,sum-node->val)||hasPathSum(node->right,sum-node->val);
}
};
给定一个二叉树,它的每个结点都存放着一个整数值。
找出路径和等于给定数值的路径总数。
路径不需要从根节点开始,也不需要在叶子节点结束,但是路径方向必须是向下的(只能从父节点到子节点)。
思路:视每个树节点为一个状态,每个状态后可以分出4个状态:
注意一旦选择要当前节点,也就是确定了开头节点,后续分岔状态则只剩下最后两种,因为是连续子序列。所以我加了个flag位记录是否确定好头节点,确定好有两种分岔,没确定好则有四种分岔。思想还是DFS。
class Solution {
public:
int ans = 0;
void helper(TreeNode* root, int sum,int flag){
if(root==NULL) return;
if(sum == root->val) {
ans++;
}
if(flag){
helper(root->left,sum-root->val,1);
helper(root->right,sum-root->val,1);
}else{
//这时候头节点没确定
helper(root->left,sum,0);
helper(root->right,sum,0);
//确定头节点了 此后只能连续
helper(root->left,sum-root->val,1);
helper(root->right,sum-root->val,1);
}
return;
}
int pathSum(TreeNode* root, int sum) {
helper(root,sum,0);
return ans;
}
};
BFS
class Solution {
public:
int maxDepth(TreeNode* root) {
queue<TreeNode* > qu;
int size,len = 0;
int max = 0,min = 0;
int flag = 0;
if (!root) return 0;
qu.push(root);
TreeNode* node;
while(!qu.empty()){
len++;
size = qu.size();
for(int i =0;i<size;i++){
node = qu.front();
qu.pop();
if(node->left) qu.push(node->left);
if(node->right) qu.push(node->right);
if(!node->left&&!node->right){
if(!flag){
min = len;
flag = 1;
}
max = max>len?max:len;
}
}
}
return max;//min的时候可以提前return
}
};
求最大深度可用DFS递归写法
int maxDepth(TreeNode* root) {
if(!root) return 0;
return 1+max(maxDepth(root->left),maxDepth(root->right));
}
Given n pairs of parentheses, write a function to generate all
combinations of well-formed parentheses.
class Solution {
public:
void backtrace(int left, int right, int n, string& s, vector<string>& res) {//引用传递
if (left == n && right == n) {
res.push_back(s);
return;
}
if (left < n) {
s += "(";
backtrace(left + 1, right, n, s, res);
s.pop_back();
}
if (right < left) {
s += ")";
backtrace(left, right + 1, n, s, res);
s.pop_back();
}
}
vector<string> generateParenthesis(int n) {
vector<string> res;
string s;
backtrace(0, 0, n, s, res);
return res;
}
};
class Solution {
vector<string> ans;
int N;
public:
vector<string> generateParenthesis(int n) {
N = n;
DFS("");
for(auto i : ans){
cout<<i<<endl;
}
return ans;
}
void DFS(string s){
if(s.length() == 2*N){
ans.push_back(s);
return;
}
DFS(s+"(");
DFS(s+")");
}
};
输入3时,输出了 2 6 2^{6} 26种左右括号的排列组合,说明是对的。接下来通过left和right变量,表示已经使用的左右括号数目,增加两种停止递归的条件即可:
class Solution {
vector<string> ans;
int N;//类变量保存不同函数所需变量
public:
vector<string> generateParenthesis(int n) {
N = n;
DFS("",0,0);
return ans;
}
void DFS(string s,int left,int right){
if(left < right) return;
if(left > N) return;//剪掉了无用分支
if(s.length() == 2*N){//符合题意的叶子节点,应保存到ans数组中
ans.push_back(s);
return;
}
DFS(s+"(",left+1,right);//string类可以直接加字符
DFS(s+")",left,right+1);
}
};