ip地址有效需要满足:遍历完s,将其分为4段,每段数字有效性:范围在[0,255],且不含前导零
为避免重复取值,需要startIndex
作为下次递归的初始位置。当遍历结束startIndex == len(s)
,且ip段数为4 len(path) == 4
加入结果,否则提前回溯。
如果当前字符串满足要求,递归调用下一层
func restoreIpAddresses(s string) []string {
res := []string{}
path := []string{}
var help func(s string, startIndex int)
help = func(s string, startIndex int) {
if len(path) == 4 {
if startIndex == len(s) {
res = append(res, strings.Join(path, "."))
}
return
}
for i := startIndex; i < len(s); i++ {
str := s[startIndex : i+1]
if isValid(str) {
path = append(path, str)
help(s, i+1)
path = path[:len(path)-1]
} else {
break
}
}
}
help(s, 0)
return res
}
func isValid(str string) bool {
if len(str) != 1 && str[0] == '0' {
return false
}
i, _ := strconv.Atoi(str)
if i > 255 {
return false
}
return true
}
子集相当于找树的节点,只要遍历到一个节点就加入结果
func subsets(nums []int) [][]int {
res := [][]int{}
path := []int{}
var help func(nums []int, startIndex int)
help = func(nums []int, startIndex int) {
tmp := make([]int,len(path))
copy(tmp,path)
res = append(res, tmp)
for i := startIndex; i < len(nums); i++ {
path = append(path, nums[i])
help(nums, i+1)
path = path[:len(path)-1]
}
}
help(nums, 0)
return res
}
相较于上题子集问题,数组有重复元素,要求结果集合不能重复,需要去重
先对数组进行排序,然后同层去重【否则,相当于当前元素要走前一个元素已经走过的路】
同层去重:used[i - 1] = false,说明是从前一个元素回溯回来的,若used[i - 1] = true说明是进入下一个递归取值
func subsetsWithDup(nums []int) [][]int {
res := [][]int{}
path := []int{}
used := make([]bool, len(nums))
sort.Ints(nums)
var help func(nums []int, startIndex int)
help = func(nums []int, startIndex int) {
tmp := make([]int, len(path))
copy(tmp, path)
res = append(res, tmp)
for i := startIndex; i < len(nums); i++ {
if i > 0 && nums[i] == nums[i-1] && used[i-1] == false {
continue
}
path = append(path, nums[i])
used[i] = true
help(nums, i+1)
used[i] = false
path = path[:len(path)-1]
}
}
help(nums, 0)
return res
}
93.复原IP地址
78.子集
90.子集II