1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93
#![allow(dead_code)] pub fn open_lock(deadends: Vec<String>, target: String) -> i32 { use std::collections::HashSet; use std::collections::LinkedList; let mut visited = HashSet::new(); let mut dead_ends = HashSet::new(); let target = target.into_bytes(); for s in deadends { dead_ends.insert(s.into_bytes()); } let mut q = LinkedList::new(); q.push_back((String::from("0000").into_bytes(), 0)); while !q.is_empty() { let cur = q.pop_front().unwrap(); match dead_ends.get(&cur.0) { Some(_) => { continue; } None => {} } match visited.get(&cur.0) { Some(_) => { continue; } None => { visited.insert(cur.0.clone()); } } if target == cur.0 { return cur.1; } let neighbors = get_neighbors(cur.0); for n in neighbors { q.push_back((n, cur.1 + 1)); } } -1 } fn get_neighbors(s: Vec<u8>) -> Vec<Vec<u8>> { let mut neighbors = Vec::with_capacity(8); let origin = s.clone(); for (i, &c) in s.iter().enumerate() { let n; if c == b'9' { n = (b'8', b'0'); } else if c == b'0' { n = (b'9', b'1'); } else { n = (c + 1, c - 1); } let mut new = origin.clone(); new[i] = n.0; neighbors.push(new); let mut new = origin.clone(); new[i] = n.1; neighbors.push(new); } neighbors } #[cfg(test)] mod tests { use super::*; #[test] fn test1() { let dead_ends = vec![ String::from("0201"), String::from("0101"), String::from("0102"), String::from("1212"), String::from("2002"), ]; let res = open_lock(dead_ends, String::from("0202")); assert_eq!(res, 6); let dead_ends = vec![String::from("8888")]; let res = open_lock(dead_ends, String::from("0009")); assert_eq!(res, 1); } }