class Solution:
def openLock(self, deadends: List[str], target: str) -> int:
def variations(lock):
variations = []
for i in range(0,4):
variations.append(lock[:i] + ('0' if lock[i] == '9' else str(int(lock[i])+1)) + lock[i+1:])
variations.append(lock[:i] + ('9' if lock[i] == '0' else str(int(lock[i])-1)) + lock[i+1:])
return variations
deadends = set(deadends)
visited = set([])
de = collections.deque([('0000', 0)])
while de:
lock = de.popleft()
if lock[0] == target:
return lock[1]
if lock[0] in deadends or lock[0] in visited:
continue
varations = variations(lock[0])
for variation in varations:
if variation not in visited:
de.append((variation, lock[1]+1))
visited.add(lock[0])
return -1
function* nextOf(n) {
for (const scale of [1, 10, 100, 1000]) {
if (Math.trunc(n / scale) % 10 === 9) {
yield n - scale * 9;
} else {
yield n + scale;
}
if (Math.trunc(n / scale) % 10 === 0) {
yield n + scale * 9;
} else {
yield n - scale;
}
}
}
var openLock = function(deadends, target) {
deadends = new Set(deadends.map(num => Number(num)));
if (deadends.has(0)) {
return -1;
}
const enqueued = new Set([0]);
let q = [0];
target = Number(target);
let rounds = 0;
while (q.length > 0) {
const next = [];
for (const n of q) {
if (n === target) {
return rounds;
}
for (const m of nextOf(n)) {
if (!enqueued.has(m) && !deadends.has(m)) {
enqueued.add(m);
next.push(m);
}
}
}
q = next;
rounds++;
}
return -1;
};
Dm chảnh thế, post code đẹp lên cho mng mở rộng tầm mắt chứToàn bài easy post lên tốn tiền net
Java:class Solution { public boolean validPath(int n, int[][] edges, int source, int destination) { List<Integer>[] graph = new List[n]; for (int[] edge: edges) { if (graph[edge[0]] == null) graph[edge[0]] = new ArrayList<>(); if (graph[edge[1]] == null) graph[edge[1]] = new ArrayList<>(); graph[edge[0]].add(edge[1]); graph[edge[1]].add(edge[0]); } boolean[] visited = new boolean[n]; return dfs(source, visited, graph, destination); } private boolean dfs(int source, boolean[] visited, List<Integer>[] graph,int destination) { if (source == destination) { return true; } visited[source] = true; for (int next: graph[source]) { if (!visited[next]) { if (dfs(next, visited, graph, destination)) { return true; } } } return false; } }
class Solution:
def openLock(self, deadends: List[str], target: str) -> int:
if "0000" in deadends:
return -1
if "0000" == target:
return 0
count = 0
mapping = {
"0" : ["9", "1"],
"1" : ["0", "2"],
"2" : ["1", "3"],
"3" : ["2", "4"],
"4" : ["3", "5"],
"5" : ["4", "6"],
"6" : ["5", "7"],
"7" : ["6", "8"],
"8" : ["7", "9"],
"9" : ["8", "0"],
}
q = deque([["0000"]])
self.visited = dict(zip(deadends, [1] * len(deadends)))
def gen_codes(codes):
res = {}
for code in codes:
for idx, char in enumerate(code):
for x in mapping[char]:
word = code[:idx] + x + code[idx+1:]
if self.visited.get(word, 0) == 0:
res[word] = 1
return res
while q:
count += 1
codes = q.popleft()
for code in codes:
if self.visited.get(code, 0) == 0:
self.visited[code] = 1
new_codes = gen_codes(codes)
if len(new_codes) == 0:
return -1
if new_codes.get(target, 0) != 0:
return count
q.append([x for x in new_codes.keys()])
Chưa compress path kìa find tới đâu update parent lại tới đấy@billy_don union find cũm khá dễ hiểu
Java:class Solution { int[] parent; public boolean validPath(int n, int[][] edges, int source, int destination) { parent=new int[n]; for(int i=0;i<n;i++){ parent[i]=i; } for(int[] edge:edges){ union(edge[0],edge[1]); } return findRoot(source) == findRoot(destination); } public int findRoot(int x){ while(x!=parent[x]){ x= parent[parent[x]]; } return x; } public void union(int x,int y){ int rootX= findRoot(x); int rootY= findRoot(y); if(rootX!= rootY){ parent[rootY]= rootX; } } }
def findMinHeightTrees(self, n: int, edges: List[List[int]]) -> List[int]:
neighbors = collections.defaultdict(set)
for v, w in edges:
neighbors[v].add(w)
neighbors[w].add(v)
def maxpath(v, visited):
visited.add(v)
paths = [maxpath(w, visited) for w in neighbors[v] if w not in visited]
path = max(paths or [[]], key=len)
path.append(v)
return path
path = maxpath(0, set())
path = maxpath(path[0], set())
m = len(path)
return path[(m-1)//2:m//2+1]
from collections import defaultdict, deque
from typing import List
class Solution:
def findMinHeightTrees(self, n: int, edges: List[List[int]]) -> List[int]:
if n == 1:
return [0]
graph = defaultdict(set)
for edge in edges:
graph[edge[0]].add(edge[1])
graph[edge[1]].add(edge[0])
queue = deque()
for key, value in graph.items():
if len(value) == 1:
queue.append(key)
while n > 2:
size = len(queue)
n -= size
for _ in range(size):
vertex = queue.popleft()
neighbor = graph[vertex].pop()
graph[neighbor].remove(vertex)
if len(graph[neighbor]) == 1:
queue.append(neighbor)
return list(queue)
import queue
class Solution:
def findMinHeightTrees(self, n: int, edges: List[List[int]]) -> List[int]:
if n == 1:
return [0]
if n == 2:
return [0, 1]
edgeHash = {}
for edge in edges:
if edge[0] in edgeHash:
edgeHash[edge[0]].add(edge[1])
else:
edgeHash[edge[0]] = {edge[1]}
if edge[1] in edgeHash:
edgeHash[edge[1]].add(edge[0])
else:
edgeHash[edge[1]] = {edge[0]}
while len(edgeHash) != 0:
leafs = []
for key in edgeHash:
if len(edgeHash[key]) <= 1:
leafs.append(key)
for leaf in leafs:
for neighbour in edgeHash[leaf]:
if neighbour in edgeHash:
edgeHash[neighbour].remove(leaf)
del edgeHash[leaf]
if len(edgeHash) == 0:
return leafs
fen còn pass dc, vẫn còn đang kẹt đâyCode xong submit thấy beat được mỗi 5%, mặt mình đần thối, ngồi đọc lại code một lúc mới hiểu tại sao
Python:import queue class Solution: def findMinHeightTrees(self, n: int, edges: List[List[int]]) -> List[int]: if n == 1: return [0] if n == 2: return [0, 1] edgeHash = {} for edge in edges: if edge[0] in edgeHash: edgeHash[edge[0]].add(edge[1]) else: edgeHash[edge[0]] = {edge[1]} if edge[1] in edgeHash: edgeHash[edge[1]].add(edge[0]) else: edgeHash[edge[1]] = {edge[0]} while len(edgeHash) != 0: leafs = [] for key in edgeHash: if len(edgeHash[key]) <= 1: leafs.append(key) for leaf in leafs: for neighbour in edgeHash[leaf]: if neighbour in edgeHash: edgeHash[neighbour].remove(leaf) del edgeHash[leaf] if len(edgeHash) == 0: return leafs
Sáng tôi làm bfs cũng chết TLE đâu đó khúc này nè, bỏ luôn rồi.fen còn pass dc, vẫn còn đang kẹt đây
View attachment 2456324
update: nhích lên dc 1 testcase
View attachment 2456350
class Solution {
public List<Integer> findMinHeightTrees(int n, int[][] edges) {
Set<Integer>[] neighbors = new HashSet[n];
Set<Integer> ans = new HashSet();
for (int i = 0; i < n; i++) {
neighbors[i] = new HashSet();
ans.add(i);
}
if (n <= 2) {
return new ArrayList(ans);
}
int[] adjs = new int[n];
for (int[] edge : edges) {
neighbors[edge[0]].add(edge[1]);
neighbors[edge[1]].add(edge[0]);
adjs[edge[0]]++;
adjs[edge[1]]++;
}
Queue<Integer> leaves = new LinkedList();
for (int i = 0; i < n; i++) {
if (adjs[i] == 1) {
leaves.add(i);
ans.remove(i);
}
}
while (ans.size() > 2) {
List<Integer> remove = new ArrayList();
while (!leaves.isEmpty()) {
remove.add(leaves.poll());
}
for (int leaf : remove) {
for (int i : neighbors[leaf]) {
if (ans.contains(i)) {
adjs[i]--;
if (adjs[i] == 1) {
leaves.add(i);
}
}
}
ans.remove(leaf);
}
}
return new ArrayList(ans);
}
}
Ai bảo fen làm nhanh hơn t@billy_donsao bác lại gạch e
đọc code python khóc thécThấy có thằng cài đặt đẹp vãi nên post cho các bác tham khảo
Python:def findMinHeightTrees(self, n: int, edges: List[List[int]]) -> List[int]: neighbors = collections.defaultdict(set) for v, w in edges: neighbors[v].add(w) neighbors[w].add(v) def maxpath(v, visited): visited.add(v) paths = [maxpath(w, visited) for w in neighbors[v] if w not in visited] path = max(paths or [[]], key=len) path.append(v) return path path = maxpath(0, set()) path = maxpath(path[0], set()) m = len(path) return path[(m-1)//2:m//2+1]
Tôi thì thấy dễ hiểu mà. Java thì dài thật sự. Code python dễ nghiện cái trò comprehension lắm.đọc code python khóc théc
java tuy wall of text nhưng mà kiên nhẫn đọc hết thì dễ hiểu.
mấy page đầu còn có bác Kanteam cố rút code ngắn nhất có thể nữa.
class Solution {
public List<Integer> findMinHeightTrees(int n, int[][] edges) {
List<Integer>[] g = new List[n];
Set<Integer> leaves = new HashSet<>();
Map<Integer, List<Integer>> layers = new HashMap<>();
if (n == 2) return List.of(0, 1);
if (n == 1) return List.of(0);
for (int[] edge: edges) {
if (g[edge[0]] == null) g[edge[0]] = new ArrayList<>();
if (g[edge[1]] == null) g[edge[1]] = new ArrayList<>();
g[edge[0]].add(edge[1]);
g[edge[1]].add(edge[0]);
}
int source = findSource(g, 0, -1, new int[n]);
int destination = findSource(g, source, -1, new int[n]);
return findMedian(g, source, destination);
}
private int findSource(List<Integer>[] g, int v, int parent, int[] dist) {
int farthestV = v;
for (int adj: g[v]) {
if (adj != parent) {
dist[adj] = dist[v] + 1;
int farthest = findSource(g, adj, v, dist);
if (dist[farthest] > dist[farthestV]) {
farthestV = farthest;
}
}
}
return farthestV;
}
public List<Integer> findMedian(List<Integer>[] g, int source, int destination) {
Stack<Integer> pathStack = new Stack<>();
dfs(g, -1, pathStack, source, destination);
System.out.println(Arrays.toString(pathStack.toArray()));
int pathLength = pathStack.size();
int medianIndex1 = pathLength / 2;
int medianIndex2 = (pathLength - 1) / 2;
List<Integer> medianPoints = new ArrayList<>();
while (!pathStack.isEmpty()) {
int vertex = pathStack.pop();
if (pathLength % 2 == 0) {
if (pathStack.size() == medianIndex1 || pathStack.size() == medianIndex2) {
medianPoints.add(vertex);
}
} else {
if (pathStack.size() == medianIndex1) {
medianPoints.add(vertex);
}
}
}
return medianPoints;
}
private void dfs(List<Integer>[] g, int parent, Stack<Integer> pathStack, int current, int destination) {
pathStack.push(current);
if (current == destination) {
return;
}
for (int neighbor : g[current]) {
if (neighbor != parent) {
dfs(g, current, pathStack, neighbor, destination);
if (!pathStack.isEmpty() && pathStack.peek() == destination) {
return;
}
}
}
pathStack.pop();
}
}