【回溯算法iii】全排列,拆分单词

排列问题

  • 排列问题,无需使用startIndex,注意同层不能重复取某一元素

全排列

// 无重复数组的全排列
func FullArray(nums []int) [][]int {
	var res [][]int
	var path []int
	var in func()
	n := len(nums)
	// 用于记录元素是否被取用过
	used := make(map[int]bool)
	in = func(){

		if len(path) == n {
			tmp := make([]int, n)
			copy(tmp, path)
			res = append(res, tmp)
			return
		}
		for i := 0; i < n; i++ {
			if used[nums[i]] {
				continue
			}
			used[nums[i]] = true
			path = append(path, nums[i])
			in()
			used[nums[i]] = false
			path = path[:len(path)-1]
		}
	}
	in()
	return res
}

拆分单词

  • 回溯算法,按照回溯算法模板处理
// 拆分字符串
func WordBreak(s string, wordDict []string) bool {
	n := len(s)
	var in func(startIndex int) bool
	memory := make(map[int]bool)
	in = func(startIndex int) bool {
		// 回溯终止条件
		if startIndex >= n {
			return true
		}
		// 记录,减少循环遍历次数
		if _, ok := memory[startIndex]; ok && !memory[startIndex] {
			return memory[startIndex]
		}
		for i := startIndex; i < n; i++ {
			tmp := i + 1
			word := s[startIndex:tmp]
			//fmt.Printf("word is %v\n", word)
			if wordDictHas(word, wordDict) && in(i+1) {
				return true
			}
		}
		memory[startIndex] = false
		return false
	}
	return in(0)
}

func wordDictHas(word string, wordDict []string) bool {
	for _, v := range wordDict {
		if word == v {
			return true
		}
	}
	return false
}

  • 动态规划算法
    1.此问题可转换为完全背包问题,重点在于遍历循序的确定,动态规划中:
    ①排列数,外层遍历背包,内层循环遍历物品
    ②组合数,外层循环遍历物品,内层循环遍历背包
// 拆分单词,字符串s是背包,单词是物品
func WordBreakI(s string, wordDict []string) bool {
	// dp[i]表示长度为i的字符串,能否被拆分
	wordMap := make(map[string]bool)
	for _, v := range wordDict {
		wordMap[v] = true
	}
	n := len(s)
	dp := make([]bool, n+1)
	// [j,i]若j到i长度的在dict中,那么dp[i]=dp[j]
	//
	dp[0] = true
	// 确定遍历顺序
	for i := 1; i <= n; i++ {
		for j := 0; j < i; j++ {
			word := s[j:i]
			if wordMap[word] && dp[j] == true {
				dp[i] = true
				break
			}
		}
	}
	fmt.Printf("dp in wordBreakI is %v\n", dp)
	return dp[n]
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值