算法训练 Day 28

LeetCode 93. 复原 IP 地址

题目链接:93. 复原 IP 地址

思路:与LeetCode第131题分割回文串很类似,只是在判断上有所不同,大致可分为三点。

  1. 我们将判断是否是回文串的函数变成了是否是合法的IP地址;
  2. 因为每个IP之间要加上"."作为分割,所以长度并不是恒定的,这是又一个细节;
  3. 递归最重要的终止条件的判断,也不能是简单的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]
	}
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值