day28
1.剑指 Offer 37. 序列化二叉树
1 /** 2 * Definition for a binary tree node. 3 * struct TreeNode { 4 * int val; 5 * TreeNode *left; 6 * TreeNode *right; 7 * TreeNode(int x) : val(x), left(NULL), right(NULL) {} 8 * }; 9 */ 10 class Codec { 11 public: 12 13 // Encodes a tree to a single string. 14 string serialize(TreeNode* root) { 15 if(root == nullptr) return "[]"; 16 string res = "["; 17 queue<TreeNode*> q; 18 q.push(root); 19 while(!q.empty()){ 20 //int n = q.size(); 21 //for(int i = 0;i < n;i ++){ 22 auto tmp = q.front(); 23 q.pop(); 24 if(tmp == nullptr) res += "null,"; 25 else{ 26 res += (to_string(tmp -> val) + ","); 27 q.push(tmp -> left); 28 q.push(tmp -> right); 29 } 30 } 31 } 32 res.pop_back(); 33 res += "]"; 34 return res; 35 } 36 37 // Decodes your encoded data to tree. 38 TreeNode* deserialize(string data) { 39 if(data == "[]") return nullptr; 40 vector<string> str; 41 str = split(data.substr(1,data.length() - 2),","); 42 TreeNode* root = new TreeNode(std::stoi(str[0])); 43 queue<TreeNode*> q; 44 q.push(root); 45 int i = 1; 46 while(!q.empty()){ 47 auto cur = q.front(); 48 q.pop(); 49 if(str[i] != "null"){ 50 cur -> left = new TreeNode(std::stoi(str[i])); 51 q.push(cur -> left); 52 } 53 i ++; 54 if(str[i] != "null"){ 55 cur -> right = new TreeNode(std::stoi(str[i])); 56 q.push(cur -> right); 57 } 58 i ++; 59 } 60 return root; 61 } 62 63 private: 64 vector<string> split(string str,string delim){ 65 vector<string> res; 66 int len = str.length(); 67 int i = 0; 68 while(i < len){ 69 int j = i; 70 while(j < len && str[j] != ',') j ++; 71 res.push_back(str.substr(i,j - i)); 72 i = ++ j; 73 } 74 return res; 75 } 76 }; 77 78 // Your Codec object will be instantiated and called as such: 79 // Codec codec; 80 // codec.deserialize(codec.serialize(root));
2.剑指 Offer 38. 字符串的排列
dfs,这种写法就是模板写法了,设一个数组visited来记录哪些元素被使用过了;dfs之前要标记visited[i] = 1,遍历之后恢复现场 visited[i] = 0;达到触发条件就返回
1 class Solution { 2 public: 3 vector<string> permutation(string s) { 4 unordered_map<char,char> map; 5 int len = s.length(); 6 for(int i = 0;i < len;i ++){ 7 if(map.find(s[i]) != map.end()) continue; 8 map[s[i]] = s[i]; 9 dfs(s,i,len,1); 10 str.pop_back(); //把第一个元素弹出来 11 } 12 return res; 13 } 14 15 private: 16 int visited[9]; 17 string str; 18 vector<string> res; 19 unordered_map<string,string> resmap; 20 void dfs(string s,int i,int len,int cnt){ 21 str += s[i]; 22 if(cnt == len){ 23 if(resmap.find(str) == resmap.end()){ 24 res.push_back(str); 25 resmap[str] = str; 26 } 27 return; 28 } 29 visited[i] = 1; 30 for(int j = 0;j < len;j ++){ 31 if(visited[j] == 0){ 32 dfs(s,j,len,cnt + 1); 33 str.pop_back(); 34 } 35 } 36 visited[i] = 0; 37 } 38 39 };
大佬简洁代码:
https://leetcode.cn/leetbook/read/illustration-of-algorithm/50hah3/
注意开头,n个字符排列有 n * (n - 1) * (n - 2) * ... * 1 种方案
就是说第一个位置有n个选择,第一个位置有字符后,第二个位置还剩下(n - 1)个选择,第二个位置有字符以后,第三个位置还剩下(n - 2)个选择,依此类推,到最后一个位置只剩一个字符,触发返回条件
第一个位置选择一个字符后遍历完了所有的可能,这个时候要在剩下的n - 1个字符中选一个放在第一个位置,依此类推,直到n个字符都在第一个位置开始,遍历过所有可能(这个时候,就要注意剪枝!如果n个字符中有重复的遍历一个就行了,否则就会重复)
下面代码是通过交换两个字符的位置来达到上面过程的效果
1 class Solution { 2 public: 3 vector<string> permutation(string s) { 4 dfs(s, 0); 5 return res; 6 } 7 private: 8 vector<string> res; 9 void dfs(string s, int x) { 10 if(x == s.size() - 1) { 11 res.push_back(s); // 添加排列方案 12 return; 13 } 14 set<int> st; 15 for(int i = x; i < s.size(); i++) { 16 if(st.find(s[i]) != st.end()) continue; // 重复,因此剪枝 17 st.insert(s[i]); 18 swap(s[i], s[x]); // 交换,将 s[i] 固定在第 x 位 19 dfs(s, x + 1); // 开启固定第 x + 1 位字符 20 swap(s[i], s[x]); // 恢复交换 21 } 22 } 23 };
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· Manus的开源复刻OpenManus初探
· AI 智能体引爆开源社区「GitHub 热点速览」
· 三行代码完成国际化适配,妙~啊~
· .NET Core 中如何实现缓存的预热?