Open azl397985856 opened 3 years ago
本题的输入比较特别, 需要自己先好好理解一下。
理解题意:
graph = [
[1],
[2],
[0]
]
target = 0
输入的解释:
index=0的结点的邻接nodes数组是: [1],
index=1的结点的邻接nodes数组是: [2],
index=2的结点的邻接nodes数组是: [0]
3
结点 0 -> 1 -> 2 -> 0
形成了一个环
graph = [
[1],
[2],
[4],
[],
[0]
]
target = 3
输入的解释:
index=0的结点的邻接nodes数组是: [1],
index=1的结点的邻接nodes数组是: [2],
index=2的结点的邻接nodes数组是: [4],
index=3的结点的邻接nodes数组是: [], 为空, 表示没与之连接的相邻结点。
index=4的结点的邻接nodes数组是: [0]
-1
#1
试试从“目标”结点运行BFS广度优先搜索并记录“visited” set。
这个题首先要理解题目的输入 - 二维矩阵(adj list), 是一个邻接表。
其中
graph = [
[1],
[2],
[0]
]
表示:
index=0的结点的邻接nodes数组是: [1],
index=1的结点的邻接nodes数组是: [2],
index=2的结点的邻接nodes数组是: [0]
从目标节点target开始往后一层一层遍历
1.先遍历target向后连接的节点们,再遍历这些节点们向后连接的节点们
2.如果遍历回target了,那就返回到目前为止遍历的次数,也就是环的大小
3.如果循环结束也没有返回,说明target不在环里,返回-1
4.遍历的过程中,注意已经遍历过的节点不能再遍历了,否则循环结束不了
实现语言: C++
int solve(vector<vector<int>>& graph, int target) {
queue<int> q;
unordered_set<int> visited;
q.push(target);
int res = 0;
while(!q.empty())
{
res++;
int size = q.size();
for(int i = 0; i < size; i++)
{
int cur = q.front();
q.pop();
for(int& next : graph[cur])
{
if(next == target)
{
return res;
}
if (visited.count(next))
continue;
visited.insert(next);
q.push(next);
}
}
}
return -1;
}
https://binarysearch.com/problems/Shortest-Cycle-Containing-Target-Node
题目也没看懂, 所以答案应该是错的
const shortestCircle = (graph, target) => {
let seen = false;
for (let i = 0; i < graph.length; i ++ ) {
if (graph[i][0] === target ) {
seen = true;
targetPos = i
}
if (!graph[i][0]) return -1
}
return graph.length
};
给的graph[][] 其实就是构好图的结果, 在target 往外BFS就好了
class Solution {
public int solve(int[][] graph, int target) {
Queue<Integer> queue = new ArrayDeque<>();
Set<Integer> visited = new HashSet<>();
queue.add(target);
visited.add(target);
int step = 0;
while (!queue.isEmpty()) {
int size = queue.size();
for (int i = 0; i < size; i++) {
int curNode = queue.poll();
for (int neighbor : graph[curNode]) {
if (neighbor == target) {
return step + 1;
}
if (!visited.contains(neighbor)) {
visited.add(neighbor);
queue.offer(neighbor);
}
}
}
step++;
}
return -1;
}
}
使用 BFS 的思路, 从 target 开始
每次添加 q 中元素的 neighbor 到 queue, 并且将 已经访问的节点添加到 visited
每一次 bfs 结束 step += 1
最后 如果 再次碰到 target, 返回 step
否则返回 -1
from collections import deque
class Solution:
def solve(self, graph, target):
n = len(graph)
q = deque()
step = 0
q.append(target)
visited = set()
while q and step <= n:
for i in range(len(q)):
j = q.popleft()
if j == target and step != 0:
return step
if j in visited:
continue
visited.add(j)
for k in graph[j]:
q.append(k)
step += 1
return -1
n 为 graph 的节点数目, e 为 边的数目
时间复杂度: O(n+e) graph 中每个节点最多加入 queue 一次, 遍历节点 neighbor 时每条边都可能被访问
空间复杂度: O(n) queue 的空间复杂度
思路: 题目已知条件是一个邻接图和目标值,本题求的是最短周期。短 = 距离 = BFS优先。 因此可以用BFS求解,将目标节点放入队列,扫描邻接数组,每次扫描加一。如果遇到目标节点则直接返回,如果遇到已经遍历过的节点继续continue循环,遇到一个新的节点要标志位置1【用一个哈希表存是否到过该节点】。 最后,如果for循环结束还没找到回去的节点,则返回-1。代表目标节点不处于循环内
func solve(graph [][]int, target int) int{
q := []int{}
hashmap := map[int]int{}
q = append(q,target)
out := 0
for len(q) >0{
out++
cur := q[0]
q = q[1:]
for _,next := range graph[cur]{
if next == target{
return out
}
if _,ok := hashmap[next];ok{
continue
}
hashmap[next]++
q = append(q,next)
}
}
return -1
}
时间复杂度:O(n) 空间复杂度:O(n)
思路: graph的第一维索引代表一个节点,第二维代表该节点向后连接的节点(邻接节点)
复杂度分析:
代码(C++):
int solve(vector<vector<int>>& graph, int target) {
queue<int> qt;
set<int> visited;
int res = 0;
qt.push(target);
while (!qt.empty()) {
size_t size = qt.size();
while (size--) {
int cur = qt.front();
qt.pop();
visited.insert(cur);
for (auto n : graph[cur]) { // all adjacent nodes of node[cur]
if (!visited.count(n))
qt.push(n);
else if (n == target)
return res + 1;
}
}
++res;
}
return -1;
}
BFS带层搜索模板,从target开始到target结束。
class Solution {
public int solve(int[][] graph, int target) {
if (graph[target].length == 0) {
return -1;
}
Queue<Integer> q = new LinkedList<>();
boolean[] visited = new boolean[graph.length];
q.offer(target);
int step = -1;
while (!q.isEmpty()) {
step++;
int size = q.size();
for (int i=0; i<size; i++) {
int v = q.poll();
if (v == target && step != 0) {
return step;
}
for (int adj : graph[v]) {
if (!visited[adj]) {
visited[adj] = true;
q.offer(adj);
}
}
}
}
return -1;
}
}
TC: O(v + e) SC: O(v)
Brute force: DFS
class Solution {
int ans = 0;
public int solve(int[][] graph, int target) {
ans = 2 * graph.length;
int[] visited = new int[graph.length];
for (int next: graph[target]) {
dfs(next, graph, target, visited, 1);
}
if (ans == 2 * graph.length) return -1;
return ans;
}
public void dfs(int cur, int[][] graph, int target, int[] visited, int distance) {
if (cur == target) {
ans = Math.min(ans, distance);
return;
}
if (visited[cur] == 1) return;
visited[cur] = 1;
for (int next: graph[cur]) {
dfs(next, graph, target, visited, distance + 1);
}
visited[cur] = 0;
}
}
class Solution {
public int solve(int[][] graph, int target) {
int[] visited = new int[graph.length];
Queue<Integer> queue = new ArrayDeque<>();
for (int next: graph[target]) {
queue.offer(next);
visited[next] = 1;
}
int len = 1;
while (!queue.isEmpty()) {
int size = queue.size();
for (int i = 0; i < size; i++) {
int cur = queue.poll();
if (cur == target) return len;
for (int next: graph[cur]) {
if (visited[next] == 0) {
queue.offer(next);
visited[next] = 1;
}
}
}
len++;
}
return -1;
}
}
python
class Solution:
def solve(self, graph, target):
queue = [target]
visited = set()
steps = 0
while queue:
for _ in range(len(queue)):
node = queue.pop(0)
visited.add(node)
for neb in graph[node]:
if neb not in visited:
queue.append(neb)
elif neb == target:
return steps + 1
steps += 1
return -1
需要使用队列进行bfs遍历。
int solve(vector<vector<int>>& graph, int target) {
int N = graph.size();
int M = graph[0].size();
int path_len = 0;
queue<int> q;
unordered_set<int> visited;
q.push(target);
while(!q.empty())
{
path_len++;
int N = q.size();
for(int i=0; i<N; i++)
{
int front = q.front();
q.pop();
for(int neighbor:graph[front])
{
if(neighbor == target)
{
return path_len;
}
if(visited.count(neighbor))
{
continue;
}
visited.insert(neighbor);
q.push(neighbor);
}
}
}
return -1;
}
Time:O(n) Space:O(n)
class Solution {
public int solve(int[][] graph, int target) {
Queue<Integer> queue = new LinkedList<>();
boolean[] visited = new boolean[graph.length];
queue.add(target);
int len = 0;
while (!queue.isEmpty()) {
int size = queue.size();
for (int i = 0; i < size; i ++) {
int t = queue.remove();
visited[t] = true;
for (int neighbor : graph[t]) {
if (neighbor == target) return len + 1;
else if (!visited[neighbor]) queue.add(neighbor);
}
}
len ++;
}
return -1;
}
}
shortest path 想 bfs。 另外一个重点在于想清楚要 offer 进 queue 的 initial value 是什么
Java Code:
import java.util.*;
class Solution {
public int solve(int[][] graph, int target) {
// reurn a cycle, what if there is no cycle. how to show there is a cycle, visited
// when find the target make a flag as true
// need to do for loops, b/c of islated points
// how many nodes? n nodes
// shortest path: bfs
Set<Integer> visited = new HashSet<>();
Deque<Integer> queue = new ArrayDeque<>();
// initial nodes? target node? is target for sure to be the the graph?
queue.offer(target);
visited.add(target);
int path = 0;
while (!queue.isEmpty()) {
int size = queue.size();
for (int i = 0; i < size; i++) {
int cur = queue.poll();
if (path != 0 && cur == target) {
return path;
}
for (int nei: graph[cur]) {
if (nei == target || !visited.contains(nei)) {
queue.offer(nei);
visited.add(nei);
}
}
}
path++;
}
return -1;
}
}
复杂度分析
n 是 rows 的长度,同时也是 nodes 的个数
方法 理解输入的核心:数组下标访问的元素对应下一个数组下标 代码
实现语言: C++
int solve(vector<vector<int>>& graph, int target) {
queue<int> q;
q.push(target);
unordered_set<int> visited;
int step = 0;
while (!q.empty()) {
int len = q.size();
for (int i = 0; i < len; i++) {
auto cur = q.front();
q.pop();
visited.insert(cur);
for (auto& it : graph[cur]) {
//return it;
if (!visited.count(it)) {
q.push(it);
} else if (it == target) {
return step + 1; //满足情况状态弹出加一
}
}
}
step += 1;//结束了一格q列表,加一
}
return -1;
}
复杂度分析 时间复杂度: O(v+e),v节点数,e边数 空间复杂度: O(v)
class Solution:
def solve(self, graph, target):
q = collections.deque([target])
visited = set()
steps = 0
while q:
for i in range(len(q)):
cur = q.popleft()
visited.add(cur)
for neighbor in graph[cur]:
if neighbor not in visited:
q.append(neighbor)
elif neighbor == target:
return steps + 1
steps += 1
return -1
没太看懂题目,先抄一个
class Solution {
solve(graph, target) {
let result = 0;
let visited = new Set([]);
let check = [target];
let length = check.length
while (length > 0){
result++;
for(let i=0; i<length; i++){
let vertex = check.shift();
for (let nextNode of graph[vertex]){
if (nextNode === target){
return result;
}else{
if (!visited.has(nextNode)){
visited.add(nextNode);
check.push(nextNode);
};
};
};
};
length = check.length;
};
return -1;
}
}
BFS:
from collections import deque
class Solution:
def solve(self, graph, target):
q = deque([target])
visited = set()
length = 0
while q:
level = deque([])
while q:
cur = q.popleft()
visited.add(cur)
for item in graph[cur]:
if item not in visited:
level.append(item)
else:
if item == target:
return length + 1
q = level
length += 1
return -1
const shortestCircle = (graph, target) => {
let seen = false;
for (let i = 0; i < graph.length; i ++ ) {
if (graph[i][0] === target ) {
seen = true;
targetPos = i
}
if (!graph[i][0]) return -1
}
return graph.length
};
这道题的重点在于如何看懂这个图,hhh,使用标准bfs可以做
class Solution:
def solve(self, graph, target):
queue = deque([target])
cnt = 0
seen = set()
first = True
found = False
while queue:
curLen = len(queue)
for _ in range(curLen):
popped = queue.popleft()
if (not first) and popped == target:
return cnt
for i in graph[popped]:
if i not in seen:
seen.add(i)
queue.append(i)
first = False
cnt+=1
return -1
时间 O(n) 空间 O(n)
Shortest-Cycle-Containing-Target-Node
入选理由
暂无
题目地址
https://binarysearch.com/problems/Shortest-Cycle-Containing-Target-Node
前置知识
题目描述
You are given a two-dimensional list of integers graph representing a directed graph as an adjacency list. You are also given an integer target.
Return the length of a shortest cycle that contains target. If a solution does not exist, return -1.
Constraints
n, m ≤ 250 where n and m are the number of rows and columns in graph