BFS问题-LeetCode 55、45、5297、127、433、434(BFS)

【LeetCode #55】跳跃游戏

给定一个非负整数数组,你最初位于数组的第一个位置。
数组中的每个元素代表你在该位置可以跳跃的最大长度。
判断你是否能够到达最后一个位置。

示例 1:
输入: [2,3,1,1,4]
输出: true
解释: 我们可以先跳 1 步,从位置 0 到达 位置 1, 然后再从位置 1 跳 3 步到达最后一个位置。

class Solution {
public:
bool canJump(vector& nums) {
int maxReach = nums[0];
for(int i = 0; i <= maxReach && i < nums.size(); i++) {
maxReach = max(maxReach, i+nums[i]);
}
if (maxReach < nums.size()-1) return false; // 最远的元素
else return true;
}
};
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/jump-game

【LeetCode #45】跳跃游戏II

给定一个非负整数数组,你最初位于数组的第一个位置。
数组中的每个元素代表你在该位置可以跳跃的最大长度。
你的目标是使用最少的跳跃次数到达数组的最后一个位置。

示例:
输入: [2,3,1,1,4]
输出: 2

class Solution {
public:
int jump(vector& nums) {
int maxReach = 0;
int step = 0;
int tmp = 0; // 保存上次的maxReach
for(int i = 0; i <= maxReach && i < nums.size()-1; i++) {
maxReach = max(maxReach, i+nums[i]);
if (i == tmp) {
step++;
tmp = maxReach;
}
}
return step;
}
};
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/jump-game-ii

【LeetCode #5297】跳跃游戏III

这里有一个非负整数数组 arr,你最开始位于该数组的起始下标 start 处。当你位于下标 i 处时,你可以跳到 i + arr[i] 或者 i - arr[i]。
请你判断自己是否能够跳到对应元素值为 0 的 任意 下标处。

注意,不管是什么情况下,你都无法跳到数组之外。

示例 1:
输入:arr = [4,2,3,0,3,1,2], start = 5
输出:true
解释:
到达值为 0 的下标 3 有以下可能方案:
下标 5 -> 下标 4 -> 下标 1 -> 下标 3
下标 5 -> 下标 6 -> 下标 4 -> 下标 1 -> 下标 3

解题思路:使用递归方法并使用dp数组来保存中间变量

class Solution {
public:
bool canReach(vector& arr, int start) {
vector dp(arr.size(), false);
return dfs(dp, arr, start);
}
private:
bool dfs(vector& dp, vector& arr, int start) {
if (start < 0 || start >= arr.size()) return false;
if (dp[start] == false) {
dp[start] = true;
if (arr[start] == 0) return true;
return dfs(dp, arr, start-arr[start]) || dfs(dp, arr, start+arr[start]);
} else
return false;
}
};
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/jump-game-iii

【LeetCode #127】单词接龙

给定两个单词(beginWord 和 endWord)和一个字典,找到从 beginWord 到 endWord 的最短转换序列的长度。转换需遵循如下规则:

每次转换只能改变一个字母。
转换过程中的中间单词必须是字典中的单词。

解题思路:

使用BFS算法,从代码结构来看,与之前二叉树层次遍历十分相似,首先看第一版,无优化版本,就是正常的BFS算法,使用flags数组来标记是否访问过,但这里,有个问题,每次查询是否转化时,都会调用canChange,但是很明显,如果wordList元素非常多,这样一个个查询就会非常慢的。
因此,在第二个版本,换了一个思路,首先建立一个hashset,然后将需要查询的beginWord中的每个字母都进行变化,然后再hashset中查询变化后的word是否存在。这样就不用遍历整个数组了,大大提高的效率!

(第一版,代码性能差的DFS,普通,无优化,2000ms)

class Solution {
public:
int ladderLength(string beginWord, string endWord, vector& wordList) {
queue que;
que.push(beginWord);
vector flags(wordList.size()+1);
int layer = 1;
while(!que.empty()) {
layer++;
int size = que.size();
while(size--) {
string cur = que.front();
que.pop();
for(int i = 0; i < wordList.size(); i++) {
if (flags[i]) continue;
if (canChange(cur, wordList[i])) {
if (wordList[i] == endWord) return layer;
que.push(wordList[i]);
flags[i] = true;
}
}
}
}
return 0;
}
private:
bool canChange(string a, string b) {
int len = a.length();
int diff = 0;
for(int i = 0; i < len; i++) {
if (a[i] != b[i]) diff++;
}
return diff == 1;
}
};
(第二版,hashset优化后,100ms,快了10倍)

class Solution {
public:
int ladderLength(string beginWord, string endWord, vector& wordList) {
int step = 0;
queue que;
unordered_set hashset(wordList.begin(), wordList.end());
if (!hashset.count(endWord)) return 0;
que.push(beginWord);
int len = beginWord.length(); // 字典中len相同
while(!que.empty()) {
step++; // BFS, 遍历完一层step++
int size = que.size();
while(size--) {
string cur = que.front();
que.pop();
for(int i = 0; i < len; i++) {
char c = cur[i]; // 缓存,下面要改变
for(int j = ‘a‘; j <= ‘z‘; j++) {
if (j == c) continue; // 跳过本身
cur[i] = j;
if (cur == endWord) return step+1;
if (!hashset.count(cur)) continue;
hashset.erase(cur); // 访问完就删除
que.push(cur);
}
cur[i] = c; // 可能一个单词可以转换多个单词
}
}
}
return 0;
}
};
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/word-ladder

【LeetCode #433】最小基因变化

一条基因序列由一个带有8个字符的字符串表示,其中每个字符都属于 "A", "C", "G", "T"中的任意一个。
假设我们要调查一个基因序列的变化。一次基因变化意味着这个基因序列中的一个字符发生了变化。
例如,基因序列由"AACCGGTT" 变化至 "AACCGGTA" 即发生了一次基因变化。

与此同时,每一次基因变化的结果,都需要是一个合法的基因串,即该结果属于一个基因库。
现在给定3个参数 — start, end, bank,分别代表起始基因序列,目标基因序列及基因库,请找出能够使起始基因序列变化为目标基因序列所需的最少变化次数。如果无法实现目标变化,请返回 -1。

解题思路:

这里只给出优化后的方案,与上一题思路一致,只是有些细小不同。

class Solution {
public:
int minMutation(string start, string end, vector& bank) {
queue que;
unordered_set hashset(bank.begin(), bank.end());
if(!hashset.count(end)) return -1;
hashset.erase(start);
hashset.erase(end);
int len = 8; // 8个
string seq = "ACGT";
int step = 0;
que.push(start);
while(!que.empty()) {
step++;
int size = que.size();
while(size--) {
string cur = que.front();
que.pop();
for(int i = 0; i < 8; i++) {
char ch = cur[i];
for(auto j: seq) {
if (j == ch) continue;
cur[i] = j;
if (cur == end) return step; // 返回变化次数
if (!hashset.count(cur)) continue;
hashset.erase(cur);
que.push(cur);
}
cur[i] = ch; // 复原
}
}
}
return -1;
}
};
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/minimum-genetic-mutation

【LeetCode #434】字符串中的单词数

统计字符串中的单词个数,这里的单词指的是连续的不是空格的字符。
请注意,你可以假定字符串里不包括任何不可打印的字符。

示例:
输入: "Hello, my name is John"
输出: 5

class Solution {
public:
int countSegments(string s) {
int i = 0;
while(i < s.length() && s[i] == ‘ ‘) i++;
if (i == s.length()) return 0;
int res = 0;
while(i < s.length()) {
while(i < s.length() && s[i] != ‘ ‘) i++;
res++;
while(i < s.length() && s[i] == ‘ ‘) i++;
}
return res;
}
};

原文地址:https://www.cnblogs.com/niaocaizhou/p/12129406.html

时间: 2024-10-30 16:55:10

BFS问题-LeetCode 55、45、5297、127、433、434(BFS)的相关文章

LeetCode 55/45 Jump Game I/II-----Greedy**

一:Jump Game 题目: Given an array of non-negative integers, you are initially positioned at the first index of the array. Each element in the array represents your maximum jump length at that position. Determine if you are able to reach the last index.

[LeetCode#55, 45]Jump Game, Jump Game II

The problem: Given an array of non-negative integers, you are initially positioned at the first index of the array. Each element in the array represents your maximum jump length at that position. Determine if you are able to reach the last index. For

[LeetCode] Sum Root to Leaf Numbers(bfs)

Given a binary tree containing digits from 0-9 only, each root-to-leaf path could represent a number. An example is the root-to-leaf path 1->2->3 which represents the number 123. Find the total sum of all root-to-leaf numbers. For example, 1 / 2 3 T

[LeetCode]55.Jump Game

题目 Given an array of non-negative integers, you are initially positioned at the first index of the array. Each element in the array represents your maximum jump length at that position. Determine if you are able to reach the last index. For example:

LeetCode 55

Jump Game Given an array of non-negative integers, you are initially positioned at the first index of the array. Each element in the array represents your maximum jump length at that position. Determine if you are able to reach the last index. For ex

[leetcode] 55. 跳跃游戏

55. 跳跃游戏 分明就是45. 跳跃游戏 II的缩水版本嘛..??,难度高的版本居然放在了前面,把像我这种有强迫症的必须按照题号刷题的人不放在眼里么... class Solution { public boolean canJump(int[] nums) { return jump(nums) != Integer.MAX_VALUE; } public int jump(int[] nums) { int f[] = new int[nums.length]; if (nums.leng

Leetcode 200.岛屿的数量 - DFS、BFS

Leetcode 200 岛屿的数量: DFS利用函数调用栈保证了检索顺序, BFS则需要自己建立队列,把待检索对象按规则入队. class Solution { // DFS解法,8ms/10.7MB,99.7% / 92% public: /** * row,col: 坐标,以0开始. * 用row和col,而不是x,y. 否则容易写成grid[x][y],顺序不对!! */ void dfs_set_zero(vector<vector<char>>& grid, i

[LeetCode] 207. 课程表(拓扑排序,BFS)

题目 现在你总共有 n 门课需要选,记为?0?到?n-1. 在选修某些课程之前需要一些先修课程.?例如,想要学习课程 0 ,你需要先完成课程 1 ,我们用一个匹配来表示他们: [0,1] 给定课程总量以及它们的先决条件,判断是否可能完成所有课程的学习? 示例 1: 输入: 2, [[1,0]] 输出: true 解释:?总共有 2 门课程.学习课程 1 之前,你需要完成课程 0.所以这是可能的. 示例 2: 输入: 2, [[1,0],[0,1]] 输出: false 解释:?总共有 2 门课程

leetCode(55):Minimum Window Substring(limits.h头文件)

Given a string S and a string T, find the minimum window in S which will contain all the characters in T in complexity O(n). For example, S = "ADOBECODEBANC" T = "ABC" Minimum window is "BANC". Note: If there is no such windo