0%

数据结构|常见算法集锦

常用的数据结构。


动态规划|股票购买问题

123买卖股票的最佳时机为例,进行剖析。

1.总体思路:穷举,或者说是状态机

在该题中,总共有三种状态:天数、可以进行的交易的数目、持有状态。然后遍历所有状态,从而得到最后的结果。(其实就是穷举的思路)代码如下:

以这道题为例,$dp[i][k][1]$ 表示在第$i$天,此刻持有股票,至今为止总共进行过$k$次交易,这个时候的总利润;$dp[i][k][0]$ 表示在第 $i$ 天,此刻没有持有股票,至今为止总共进行过$k$次交易,这个时候的总利润。

2.状态转移框架

image-20191018213809486

上述图片解释了状态转移框架。在这里,需要注意两点:

​ 第一:在计算的时候,我们需要用到,在这里,需要将$k$变成$k-1$,因为正是因为在$i-1$天没有进行持有股票,那么经过一次交易后,才会在$i$天持有股票,那么自然而言的,交易次数要增加1.

​ 第二:在从无到持有股票的过程中,需要减去股票的价值;而反过程中,需要加上股票的价值。


3.base case的处理

状态转移方程:

在状态转移方程当中,当$i=0$的时候,需要计算$dp[-1]$。那么实际上index为-1,其实是有问题的,所以我们需要通过一些方法处理这些case。

实际上,处理这些base case,也是根据状态转移方程来进行分析。当$i=0$的时候,其状态转移方程为下:

那么具体分析上述方程的细节。$dp[-1][k][0]$表示的是第-1天的时候,不持有股票。那么实际上天数是从第0天开始的,当$i=-1$的时候,意味着还没有开始。所以:$dp[-1][k][0]=0$。$dp[-1][k-1][1]$表示是在第-1天的时候,持有股票。实际上,当还没有开始的时候,是不可能持有股票的。所以:$dp[-1][k-1][1]=-infinity$

。其他的依次类推。


4.程序代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
#include<stdio.h>
#include<string.h>
#include<string>
#include<algorithm>
#include<iostream>
#include<vector>
#define INF 0x3f3f3f3f
#define NINF -INF-1
using namespace std;
//还是套用公式,这是k=2的情况
class Solution{
public:
int maxProfit(vector<int>& prices) {
int n=prices.size();
if(n==0){
return 0;
}

int k_max=2;
int dp[n+1][k_max+1][2];
memset(dp,0,sizeof(dp));

for(int i=0;i<n;i++){
for(int k=k_max;k>=1;k--){
if(i-1==-1){
dp[i][k][0]=0;
dp[i][k][1]=-prices[i];
continue;
}
dp[i][k][0]=max(dp[i-1][k][0],dp[i-1][k][1]+prices[i]);
dp[i][k][1]=max(dp[i-1][k][1],dp[i-1][k-1][0]-prices[i]);
}
}
return dp[n-1][k_max][0];

}
};

int main(){
int n;
scanf("%d",&n);
vector<int> prices;
for(int i=0;i<n;i++){
int x;
scanf("%d",&x);
prices.push_back(x);
}

Solution so1;
int ans = so1.maxProfit(prices);
printf("%d\n",ans);
return 0;
}

其他的关于股票的问题还有:121. 买卖股票的最佳时机122. 买卖股票的最佳时机 II188. 买卖股票的最佳时机 IV309. 最佳买卖股票时机含冷冻期714. 买卖股票的最佳时机含手续费。套用框架均可以解决。

OK,终于写完了~🤩☕️

DFS(二叉树路径和问题)

543. 二叉树的直径

给定一棵二叉树,你需要计算它的直径长度。一棵二叉树的直径长度是任意两个结点路径长度中的最大值。这条路径可能穿过也可能不穿过根结点。

示例 :
给定二叉树

      1
     / \
    2   3
   / \     
  4   5    

返回 3, 它的长度是路径 [4,2,1,3] 或者 [5,2,1,3]。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
/**
* 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:
int diameterOfBinaryTree(TreeNode* root) {
if(root==nullptr) return 0;

int ans=0;
depth(root,ans);

return ans-1;
}

int depth(TreeNode * root,int &ans){
if(root==0) return 0;

int l=depth(root->left,ans);
int r=depth(root->right,ans);

ans=max(ans,l+r+1);

return max(l,r)+1;
}


};

124. 二叉树中的最大路径和

给定一个非空二叉树,返回其最大路径和。

本题中,路径被定义为一条从树中任意节点出发,沿父节点-子节点连接,达到任意节点的序列。该路径至少包含一个节点,且不一定经过根节点。

示例 1:

输入:[1,2,3]

   1
  / \
 2   3

输出:6
示例 2:

输入:[-10,9,20,null,null,15,7]

-10
/ \
9 20
/ \
15 7

输出:42

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
/**
* Definition for a binary tree node.
* struct TreeNode {
* int val;
* TreeNode *left;
* TreeNode *right;
* TreeNode() : val(0), left(nullptr), right(nullptr) {}
* TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
* TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
* };
*/
class Solution {
public:
int maxPathSum(TreeNode* root) {
if(root==nullptr) return 0;

int ans=root->val;
helper(root,ans);

return ans;
}

int helper(TreeNode * root,int &ans){
if(root==nullptr) return 0;

int l=max(0,helper(root->left,ans));
int r=max(0,helper(root->right,ans));

ans=max(ans,l+r+root->val);

return max(l,r)+root->val;
}
};

687. 最长同值路径

给定一个二叉树,找到最长的路径,这个路径中的每个节点具有相同值。 这条路径可以经过也可以不经过根节点。

注意:两个节点之间的路径长度由它们之间的边数表示。

示例 1:

输入:

          5
         / \
        4   5
       / \   \
      1   1   5

输出:

2
示例 2:

输入:

          1
         / \
        4   5
       / \   \
      4   4   5

输出:

2
注意: 给定的二叉树不超过10000个结点。 树的高度不超过1000。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
/**
* Definition for a binary tree node.
* struct TreeNode {
* int val;
* TreeNode *left;
* TreeNode *right;
* TreeNode() : val(0), left(nullptr), right(nullptr) {}
* TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
* TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
* };
*/
class Solution {
public:
int longestUnivaluePath(TreeNode* root) {
if(root==nullptr) return 0;

int ans=1;
dfs(root,ans);

return ans-1;
}

int dfs(TreeNode * root,int &ans){
if(root==nullptr) return 0;

int l=dfs(root->left,ans);
if(l!=0 && root->left->val != root->val) l=0;
int r=dfs(root->right,ans);
if(r!=0 && root->right->val != root->val) r=0;

ans=max(ans,l+r+1);

return max(l,r)+1;
}
};
Would you like to buy me a cup of coffee☕️~