算法
来源:(力扣)449. 序列化和反序列化二叉搜索树
序列化是将数据结构或对象转换为一系列位的过程,以便它可以存储在文件或内存缓冲区中,或通过网络连接链路传输,以便稍后在同一个或另一个计算机环境中重建。
设计一个算法来序列化和反序列化 二叉搜索树 。 对序列化/反序列化算法的工作方式没有限制。 您只需确保二叉搜索树可以序列化为字符串,并且可以将该字符串反序列化为最初的二叉搜索树。
编码的字符串应尽可能紧凑。
示例 1:
输入:root = [2,1,3]
输出:[2,1,3]
示例 2:
输入:root = []
输出:[]
提示:
树中节点数范围是 [0, 104]
0 <= Node.val <= 104
题目数据 保证 输入的树是一棵二叉搜索树。
注意:不要使用类成员/全局/静态变量来存储状态。 你的序列化和反序列化算法应该是无状态的。
解题思路
题目的反序列和序列化说的很高大上,其实就是把二叉树转成字符串,字符串转成二叉树。首先二叉搜索树定义需要知道,就是左子树比右子树小,中间的根就是两边的界限。
例图:
把二叉树转成字符串不难,但是要注意几点:用前序,中序还是后序来遍历?数字如何转成字符串?形成字符串后如何区分开每个节点的数字?
第一个问题我们最后讲,第二个问题我们举例子:12345转成字符串,12345%10得到 5变成字符就需要加‘0’,由于我们是从最后面加的所以得到的字符串是‘54321’,让字符串翻转就好了。第三个问题就是在每个节点之间加一个字符(除了一些个别字符和数字之外)例如#,如上图得到的话应该是12#5#2#9…,第一个问题应该选哪个,按道理来说选哪个都可我们都能将其转成字符串,但是转成的字符串又是否可以转成原先的二叉树呢?只有前序可以做到(个人认为,有误可以交流)。有了上述思路之后,实现代码就好了。
代码
/**
* Definition for a binary tree node.
* struct TreeNode {
* int val;
* TreeNode *left;
* TreeNode *right;
* TreeNode(int x) : val(x), left(NULL), right(NULL) {}
* };
*/
class Codec {
public:
void change(int val,string &str){
string tmp;
while(val){
tmp+=val % 10+'0';
val= val / 10;
}
for(int i=tmp.length()-1;i>=0;i--){
str+=tmp[i];
}
str+='#';
}
void BST_preorder(TreeNode*node,string &data){
if(!node){
return;
}
string str;
change(node->val,str);
data+=str;
BST_preorder(node->left,data);
BST_preorder(node->right,data);
}
void BST_insert(TreeNode*node,TreeNode* insert_node){
if(insert_node->val<node->val){
if(node->left){
BST_insert(node->left,insert_node);
}else{
node->left=insert_node;
}
}else{
if(node->right){
BST_insert(node->right,insert_node);
}else{
node->right=insert_node;
}
}
}
// Encodes a tree to a single string.
string serialize(TreeNode* root) {
string data;
BST_preorder(root,data);
return data;
}
// Decodes your encoded data to tree.
TreeNode* deserialize(string data) {
if(data.length()==0){
return NULL;
}
vector<TreeNode*>node_vec;
int val=0;
for(int i=0;i<data.length();i++){
if(data[i]=='#'){
node_vec.push_back(new TreeNode(val));
val=0;
}else{
val=val*10+data[i]-'0';
}
}
for(int i=1;i<node_vec.size();i++){
BST_insert(node_vec[0],node_vec[i]);
}
return node_vec[0];
}
};
// Your Codec object will be instantiated and called as such:
// Codec* ser = new Codec();
// Codec* deser = new Codec();
// string tree = ser->serialize(root);
// TreeNode* ans = deser->deserialize(tree);
// return ans;
== 来源:(力扣)70. 爬楼梯==
假设你正在爬楼梯。需要 n 阶你才能到达楼顶。
每次你可以爬 1 或 2 个台阶。你有多少种不同的方法可以爬到楼顶呢?
注意:给定 n 是一个正整数。
示例 1:
输入: 2
输出: 2
解释: 有两种方法可以爬到楼顶。
1 阶 + 1 阶
2 阶
示例 2:
输入: 3
输出: 3
解释: 有三种方法可以爬到楼顶。
1 阶 + 1 阶 + 1 阶
1 阶 + 2 阶
2 阶 + 1 阶
解题思路
这题不要正着想,比如到第3个台阶方法有几种,然后硬数,数字一大这样就要到猴年马月。主要是要找到规律,到5个台阶的话只能从第3或第4个台阶上去也就是我们只需要知道到第三个台阶有几种加上到第四台阶有几种,这样就能解开第五个台阶。
代码
class Solution {
public:
int climbStairs(int n) {
vector<int> dp(n+3,0);
dp[1]=1;
dp[2]=2;
for(int i=3;i<=n;i++){
dp[i]=dp[i-1]+dp[i-2];
}
return dp[n];
}
};