leetcode第139题 单词的拆分

leetcode第139题 单词的拆分

**需求:**给定义一个字符串和一个字符串数组,看看字符串是不是可以由空格拆分成一个或者是多个在字典中出现的单词

**思路:**暴力破解

  1. 从0开始一个一个的列举,假如匹配到了一个数组中的字符串,我就继续匹配,如果接下来的也能够匹配成功,返回true
  2. 用了一个备忘录记录我已经匹配的结果
  3. start代表的是节点的状态
  4. 用一个数组,存储计算的结果,下次遇到相同的子问题,直接返回命中的缓存值,就不用调重复的递归

DFS+记忆化代码

func canBreak(start int, s string, wordMap map[string]bool, memo map[int]bool) bool {
	if start == len(s) {
		return true
	}
	if res, ok := memo[start]; ok {
		return res
	}
    //这里为什么会是start + 1呢? 我有点不太理解           
	for i := start + 1; i <= len(s); i++ {
		prefix := s[start:i]
		if wordMap[prefix] && canBreak(i, s, wordMap, memo) {
			memo[start] = true
			return true
		}
	}
	memo[start] = false
	return false
}


func wordBreak(s string, wordDict []string) bool {
	wordMap := map[string]bool{}
	for _, v := range wordDict {
		wordMap[v] = true
	}
	memo := make(map[int]bool)
	return canBreak(0, s, wordMap, memo)
}

BFS

  1. 这种Bfs和我平时写的不是很一样,他是对多种情况进行处理的,我必须命中至少一个字符串数组中的一个元素,匹配一个过一个,当匹配到最后一个的时候,我们发现i == len 可以return true
func wordBreak(s string, wordDict []string) bool {
	l := len(s)
	wordMap := map[string]bool{}
	for _, v := range wordDict {
		wordMap[v] = true
	}
	queue := []int{}
	queue = append(queue, 0)
	visited := map[int]bool{}

	for len(queue) != 0 {
		start := queue[0]
		queue = queue[1:]
		if visited[start] {
			continue
		}
		visited[start] = true
		for i := start + 1; i <= l; i++ {
			prefix := s[start:i]
			if wordMap[prefix] {
				if i < l {
					queue = append(queue, i)
				} else {
					return true
				}
			}
		}
	}
	return false
}

动态规划

动态规划写的时候还算是比较顺手的,因为已经把回溯的那种情况写出来了

  1. dp数组的定义 dp[i] 以i结尾的字符串可以拆分成字典中的所有字符串。
  2. base case:dp[0] === true 意思是 以0结尾的字符串可以被拆分出来字典中的所有字符
  3. 只有让dp【0】为真,的dp【i + 1】才会只取决于s【0 :i】是否为单个的单词,才能用上这个状态转移方程

优化:

执行的过程中,发现dp【i】 == true 直接跳出内层循环

当dp【j】 == false continue

func wordBreak(s string, wordDict []string) bool {
	wordMap := map[string]bool{}
	for _, v := range wordDict {
		wordMap[v] = true
	}
	dp := make([]bool, len(s)+1)
	dp[0] = true

	for i := 1; i <= len(s); i++ {
		for j := i - 1; j >= 0; j-- {
			if dp[i] == true {
				break
			}
			if dp[j] == false {
				continue
			}
			suffix := s[j:i]
			if wordMap[suffix] && dp[j] {
				dp[i] = true
				break
			}
		}
	}
  return dp[len(s)]
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值