1. 程式人生 > 遊戲 >《特種部隊:蛇眼起源》開啟預售!全新特輯揭祕蛇眼、白幽靈兄弟情仇

《特種部隊:蛇眼起源》開啟預售!全新特輯揭祕蛇眼、白幽靈兄弟情仇

題目【來源:力扣】:

你有一個帶有四個圓形撥輪的轉盤鎖。每個撥輪都有10個數字: '0', '1', '2', '3', '4', '5', '6', '7', '8', '9' 。每個撥輪可以自由旋轉:例如把 '9' 變為'0','0' 變為 '9' 。每次旋轉都只能旋轉一個撥輪的一位數字。鎖的初始數字為 '0000' ,一個代表四個撥輪的數字的字串。列表 deadends 包含了一組死亡數字,一旦撥輪的數字和列表裡的任何一個元素相同,這個鎖將會被永久鎖定,無法再被旋轉。字串 target 代表可以解鎖的數字,你需要給出解鎖需要的最小旋轉次數,如果無論如何不能解鎖,返回-1

示例:

輸入:deadends = ["0201","0101","0102","1212","2002"], target = "0202"
輸出:6
解釋:
可能的移動序列為 "0000" -> "1000" -> "1100" -> "1200" -> "1201" -> "1202" -> "0202"。
注意 "0000" -> "0001" -> "0002" -> "0102" -> "0202" 這樣的序列是不能解鎖的,
因為當撥動到 "0102" 時這個鎖就會被鎖定。

程式碼【來源:力扣】:

public int openLock(String[] deadends, String target) {
Set<String> set = new HashSet<>(Arrays.asList(deadends));
//開始遍歷的字串是"0000",相當於根節點
String startStr = "0000";
if (set.contains(startStr))
return -1;
//建立佇列
Queue<String> queue = new LinkedList<>();
//記錄訪問過的節點
Set<String> visited = new HashSet<>();
queue.offer(startStr);
visited.add(startStr);
//樹的層數
int level = 0;
while (!queue.isEmpty()) {
//每層的子節點個數
int size = queue.size();
while (size-- > 0) {
//每個節點的值
String str = queue.poll();
//對於每個節點中的4個數字分別進行加1和減1,相當於建立8個子節點,這八個子節點
//可以類比二叉樹的左右子節點
for (int i = 0; i < 4; i++) {
char ch = str.charAt(i);
//strAdd表示加1的結果,strSub表示減1的結果
String strAdd = str.substring(0, i) + (ch == '9' ? 0 : ch - '0' + 1) + str.substring(i + 1);
String strSub = str.substring(0, i) + (ch == '0' ? 9 : ch - '0' - 1) + str.substring(i + 1);
//如果找到直接返回
if (str.equals(target))
return level;
//不能包含死亡數字也不能包含訪問過的字串
if (!visited.contains(strAdd) && !set.contains(strAdd)) {
queue.offer(strAdd);
visited.add(strAdd);
}
if (!visited.contains(strSub) && !set.contains(strSub)) {
queue.offer(strSub);
visited.add(strSub);
}
}
}
//當前層訪問完了,到下一層,層數要加1
level++;
}
return -1;
}

分析:

這道題,剛開始做的時候沒有想過用BFS,只是簡單的進行分析,覺得一個字串中四個字元,每個字元都要兩種變換情況加1和減1。剛開始寫的時候程式碼如下,寫了一點就不會了。

而該題使用bfs。因為初始數字為 '0000' ,把‘0000’看作根節點,而對於每一個字元都有兩種情況,所以根節點的子節點就有八種情況。依次往下推每一個節點都有八種情況。

但是要注意的是每一層的節點不能重複,所以需要我們記錄每一個節點的訪問情況,如果訪問則說明已經生成,下面生成的節點要進行比較,相同的不生成。

本題最終要求的是最少改變幾次,而每改變一次最多生成的結果就是樹一層,所以要記錄生成的樹的實時層數,這裡使用level記錄。每生成一個結點與最終的結果target比較如果相同,此時的level就是最終的結果;如果不相同,則繼續。