广度优先搜索,暴力搜索---------单词拆分-----bfs

广度优先搜索,暴力搜索

 

广度优先搜索的时候要清晰的知道我们在遍历什么,加入队列就是我们的遍历的目标,遍历的时候注意什么时候是结束条件,什么条件是将下个遍历的元素加入队列,存在重复遍历的位置的时候,需要一个是否访问过的变量进行记录访问的状态,不然会重复遍历,剪枝能够大大提高时间。

模板不难,难的是知道我们在遍历什么,DFS常用于最小路径,把一些遍历的node当作无向图里的节点。

 

 

139. 单词拆分

难度中等415

给定一个非空字符串 s 和一个包含非空单词列表的字典 wordDict,判定 s 是否可以被空格拆分为一个或多个在字典中出现的单词。

说明:

  • 拆分时可以重复使用字典中的单词。
  • 你可以假设字典中没有重复的单词。

示例 1

输入: s = "leetcode", wordDict = ["leet", "code"]

输出: true

解释: 返回 true 因为 "leetcode" 可以被拆分成 "leet code"

示例 2

输入: s = "applepenapple", wordDict = ["apple", "pen"]

输出: true

解释: 返回 true 因为 "applepenapple" 可以被拆分成 "apple pen apple"

     注意你可以重复使用字典中的单词。

示例 3

输入: s = "catsandog", wordDict = ["cats", "dog", "sand", "and", "cat"]

输出: false

 

  1. 暴力搜索的时候需要进行剪枝,否则时间复杂度过不了,我做的时候,没有考虑到剪枝,导致超时

#include <queue>

#include <set>

#include <vector>

#include <algorithm>

#include <string>

#include <iostream>

 

using namespace std;

 

class Solution {

public:

    bool WordDFS(int pos, string s, vector<string>& wordDict, vector<int> &visited)

    {

        if (pos == s.length()) {

            return true;

        }

        // 产生剪枝,不然会过多的重复

        if (visited[pos] == 1) {

            return true;

        } else if (visited[pos] == 2) {

            return false;

        }

        // 存在先找小的

        for (int end = s.length() - 1; end >= pos; end--) {

            if (find(wordDict.begin(), wordDict.end(), s.substr(pos, end - pos + 1)) != wordDict.end() &&

                WordDFS(end + 1, s, wordDict, visited)) {

                visited[pos] = 1;

                return true;

            }

        }

        visited[pos] = 2;

        return false;

    }

    bool wordBreak(string s, vector<string>& wordDict) {

        vector<int> visited(s.length(), 0);

        return WordDFS(0, s, wordDict, visited);

    }

};

 

2 bfs

 

class Solution {

public:

    bool WordBFS(string s, vector<string>& wordDict)

    {

        // 转换成set方便查询是否存在

        set<string> wordDic(wordDict.begin(), wordDict.end());

        // 广度优先算法必有队列,进行遍历的结构体

        queue<int> q;

        q.push(0);

        // 剪枝,对已经访问过的位置进行记录,产生剪枝

        set<int> visited;

 

        while (!q.empty()) {

            int size = q.size();

            // 模板

            for (int index = 0; index < size; index++) {

                int tmp = q.front();

                q.pop();

                // 差异性处理,对从队列的访问的地址开始向后遍历字符串

                for (int end = tmp + 1; end <= s.length(); end++) {

                    // 不存在的时候遍历下一个子字符串

                    if (wordDic.count(s.substr(tmp, end - tmp)) == 0) {

                        continue;

                    }

                    // 结束条件是遍历到最后并且都存在

                    if (end == s.length()) {

                        return true;

                    }

                    // 剪枝,从找到的这个字符串的下一个位置开始找

                    if (visited.count(end) == 0) { 

                        visited.insert(end);

                        q.push(end);

                    }

                }

            }

        }

        return false;

    }

    bool wordBreak(string s, vector<string>& wordDict) {

        if (s.length() == 0 || wordDict.empty()) {

            return false;

        }

        return WordBFS(s, wordDict);

    }

};

 

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值