Skip to content

Commit 175ad4b

Browse files
author
Obsession-kai
committed
update day28/31
1 parent 9cbec44 commit 175ad4b

File tree

2 files changed

+168
-0
lines changed

2 files changed

+168
-0
lines changed
Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,84 @@
1+
// 题目链接:https://leetcode.cn/problems/zi-fu-chuan-de-pai-lie-lcof/?envType=study-plan&id=lcof
2+
// day28/31
3+
// 第 28 天主题为:搜索与回溯算法(困难)
4+
// 包含两道题目:
5+
// 剑指offer37.序列化二叉树
6+
// 剑指offer38.字符串的排列
7+
package main
8+
9+
import (
10+
"fmt"
11+
"sort"
12+
)
13+
14+
//全排列问题,如果题目所给字符不包含重复字符,用下面简单回溯即可:
15+
func permutation(s string) []string {
16+
res := []string{}
17+
n := len(s)
18+
used := make([]bool,n)
19+
var backtrace func(path string)
20+
backtrace = func(path string){
21+
if len(path) == n{
22+
res = append(res,path)
23+
return
24+
}
25+
for i:=0;i<n;i++{
26+
if used[i]{
27+
continue
28+
}
29+
path += string(s[i])
30+
used[i] = true
31+
backtrace(path)
32+
path = path[:len(path)-1]
33+
used[i] = false
34+
}
35+
}
36+
backtrace("")
37+
return res
38+
}
39+
40+
//本题的难点在于不能有重复元素,这也就意味着输入字符串中包含重复元素。上面的代码不再可行
41+
//用集合去重是可行的,但太过笨重,试想是否可以改善回溯过程,得到不含重复元素的排列。
42+
//
43+
//去重,很容易想到要先对元素进行排序,这样才能判断相邻的节点是否重复使用了。
44+
//回溯的问题在纸上都可以画成一个树的结构,横向迭代+纵向递归。
45+
//针对本题,画出该树结构,可以发现同一树层上,若当前节点与上一个节点值相同,则对该节点回溯的结果与上一节点相同,意味着可以跳过此节点,迭代至下一节点。
46+
//那同一个树枝呢?同一树枝上,若上一个节点使用过,该节点还是可以使用的,因为这是一个正常的排列。
47+
//接下来就是代码实现,当前元素与上一个元素值相同的情况下,判断是在同一树枝,还是同一树层。
48+
// used[i-1]=true 说明上一节点已使用,说明是同一树枝
49+
// used[i]=false,说明为同一树层,可跳过此次回溯
50+
51+
func permutation_2(s string) []string {
52+
runeS := []byte(s)
53+
sort.Slice(runeS, func(i, j int) bool {
54+
return runeS[i] < runeS[j]
55+
})
56+
n := len(runeS)
57+
res := []string{}
58+
used := make([]bool,n)
59+
var backtrace func(path []byte)
60+
backtrace = func(path []byte) {
61+
if len(path) == n{
62+
res = append(res,string(path))
63+
return
64+
}
65+
for i:=0;i<n;i++{
66+
if used[i]{
67+
continue
68+
}
69+
if i>0 && runeS[i-1]==runeS[i] && !used[i-1]{
70+
continue
71+
}
72+
used[i] = true
73+
path = append(path,runeS[i])
74+
backtrace(path)
75+
path = path[:len(path)-1]
76+
used[i] = false
77+
}
78+
}
79+
backtrace([]byte{})
80+
fmt.Println(runeS)
81+
return res
82+
}
83+
84+
//本题解题思路与 LeetCode 48:全排列 II 完全一致,有兴趣可以再去做做练习一下
Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,84 @@
1+
//题目链接:https://leetcode.cn/problems/xu-lie-hua-er-cha-shu-lcof/?envType=study-plan&id=lcof
2+
package main
3+
4+
import (
5+
"strconv"
6+
"strings"
7+
)
8+
9+
//本题接参考自官方题解:https://leetcode.cn/problems/serialize-and-deserialize-binary-tree/solution/er-cha-shu-de-xu-lie-hua-yu-fan-xu-lie-hua-by-le-2/
10+
//
11+
//二叉树的序列化本质上是对其值进行编码,更重要的是对其结构进行编码。可以遍历树来完成上述任务。
12+
//众所周知,我们一般有两个策略:广度优先搜索和深度优先搜索。
13+
//广度优先搜索可以按照层次的顺序从上到下遍历所有的节点
14+
//
15+
//深度优先搜索可以从一个根开始,一直延伸到某个叶,然后回到根,到达另一个分支。
16+
//根据根节点、左节点和右节点之间的相对顺序,可以进一步将深度优先搜索策略区分为:先序遍历、中序遍历 以及 后序遍历。
17+
//
18+
//对题目所给例子进行举例,最终序列化字符串是 1,2,3,None,None,4,None,None,5,None,None,。
19+
//其中,None,None 用来标记缺少左右子节点,这是我们在序列化期间保存树结构的方式。
20+
//
21+
//即我们可以先序遍历这颗二叉树,遇到空子树的时候序列化成 None,否则继续递归序列化。那么我们如何反序列化呢?
22+
//首先我们需要根据 , 把原先的序列分割开来得到先序遍历的元素列表,然后从左向右遍历这个序列:
23+
//- 如果当前的元素为 None,则当前为空树
24+
//- 否则先解析这棵树的左子树,再解析它的右子树
25+
26+
//Definition for a binary tree node.
27+
type TreeNode struct {
28+
Val int
29+
Left *TreeNode
30+
Right *TreeNode
31+
}
32+
33+
34+
type Codec struct {
35+
36+
}
37+
38+
func Constructor() Codec {
39+
return Codec{}
40+
}
41+
42+
// Serializes a tree to a single string.
43+
func (this *Codec) serialize(root *TreeNode) string {
44+
var sb strings.Builder
45+
var preorder func(root *TreeNode)
46+
preorder = func(root *TreeNode) {
47+
if root == nil{
48+
sb.WriteString("nil,")
49+
return
50+
}
51+
sb.WriteString(strconv.Itoa(root.Val))
52+
sb.WriteString(",")
53+
preorder(root.Left)
54+
preorder(root.Right)
55+
}
56+
preorder(root)
57+
return sb.String()
58+
}
59+
60+
// Deserializes your encoded data to tree.
61+
func (this *Codec) deserialize(data string) *TreeNode {
62+
s := strings.Split(data,",")
63+
var build func() *TreeNode
64+
build = func() *TreeNode {
65+
if s[0] == "nil"{
66+
s = s[1:]
67+
return nil
68+
}
69+
val,_ := strconv.Atoi(s[0])
70+
s = s[1:]
71+
node := &TreeNode{val,build(),build()}
72+
return node
73+
}
74+
return build()
75+
}
76+
77+
78+
/**
79+
* Your Codec object will be instantiated and called as such:
80+
* ser := Constructor();
81+
* deser := Constructor();
82+
* data := ser.serialize(root);
83+
* ans := deser.deserialize(data);
84+
*/

0 commit comments

Comments
 (0)