LeetCode 93. 复原 IP 地址
题目链接:93. 复原 IP 地址
思路:与LeetCode第131题分割回文串很类似,只是在判断上有所不同,大致可分为三点。
- 我们将判断是否是回文串的函数变成了是否是合法的IP地址;
- 因为每个IP之间要加上"."作为分割,所以长度并不是恒定的,这是又一个细节;
- 递归最重要的终止条件的判断,也不能是简单的start==len(s)了,我们设置了一个pointNum变量来记录已经成功添加的"."的分隔符的数量,当分隔符已经有三个的时候(有效IP地址由4段整数组成),我们判断最后一段如果也符合IP规范的话,就是一段合法的IP地址。
Python版本:
class Solution:
def restoreIpAddresses(self, s: str) -> List[str]:
def isValid(s, start, end):
if start > end:
return False
if s[start] == "0" and start < end:
return False
if not (0 <= int(s[start:end+1]) <= 255):
return False
return True
def backtrack(start, path, pointNum):
if pointNum==3:
if isValid(path, start, len(path)-1):
res.append(path[:])
return
for i in range(start, len(path)):
if isValid(path, start, i):
path = path[:i+1] + "." + path[i+1:]
backtrack(i+2, path, pointNum+1)
path = path[:i+1] + path[i+2:]
if len(s) > 12:
return []
res = []
backtrack(0, s, 0)
return res
go版本:
var res []string
func restoreIpAddresses(s string) []string {
var path []string
res = []string{}
backTracking(s, path, 0)
return res
}
func backTracking(s string, path []string, start int) {
if start == len(s) && len(path) == 4 {
tmpIpString := path[0] + "." + path[1] + "." + path[2] + "." + path[3]
res = append(res, tmpIpString)
}
for i := start; i < len(s); i++ {
path := append(path, s[start:i+1])
if i-start+1 <= 3 && len(path) <= 4 && isValid(s, start, i) {
backTracking(s, path, i+1)
} else {
return
}
path = path[:len(path)-1]
}
}
func isValid(s string, start, end int) bool {
checkInt, _ := strconv.Atoi(s[start : end+1])
if end-start+1 > 1 && s[start] == '0' {
return false
}
if checkInt > 255 {
return false
}
return true
}
LeetCode 78. 子集
题目链接:78. 子集
思路:很基础的回溯思路。
Python版本:
class Solution:
def subsets(self, nums: List[int]) -> List[List[int]]:
def backtrack(cur, path):
res.append(path[:])
for i in range(cur, len(nums)):
path.append(nums[i])
backtrack(i+1, path)
path.pop()
res = []
backtrack(0, [])
return res
go版本:
var res [][]int
func subsets(nums []int) [][]int {
res = [][]int{}
path := make([]int, 0)
backtrack(0, path, nums)
return res
}
func backtrack(start int, path, nums []int) {
tmp := make([]int, len(path))
copy(tmp, path)
res = append(res, tmp)
for i:=start; i<len(nums); i++ {
path = append(path, nums[i])
backtrack(i+1, path, nums)
path = path[:len(path)-1]
}
}
LeetCode 90. 子集 II
题目链接:90. 子集 II
思路:相比上一题增加了去重的操作,去重需要将数组先排序,便于逻辑判断。详情可以看我上一篇博客:算法训练 Day 27
Python版本:
class Solution:
def subsetsWithDup(self, nums: List[int]) -> List[List[int]]:
res = []
path = []
nums.sort()
def backtrack(nums, start):
res.append(path[:])
if start == len(nums):
return
for i in range(start, len(nums)):
if i > start and nums[i] == nums[i-1]:
continue
path.append(nums[i])
backtrack(nums, i+1)
path.pop()
backtrack(nums, 0)
return res
go版本:
var res [][]int
func subsetsWithDup(nums []int) [][]int {
res = make([][]int, 0)
sort.Ints(nums)
backtrack([]int{}, nums, 0)
return res
}
func backtrack(path, num []int, start int) {
tmp := make([]int, len(path))
copy(tmp, path)
res = append(res, tmp)
for i := start; i < len(num); i++ {
if i > start && num[i] == num[i-1] {
continue
}
path = append(path, num[i])
backtrack(path, num, i+1)
path = path[:len(path)-1]
}
}