簡體   English   中英

如何打印出BFS所走的路徑?

[英]How to print out the path taken by the BFS?

我正在解決 Leetcode 中的一個問題,我們給出了一個鎖組合,可以從 0000 的起始組合到達。您一次只能旋轉一個鎖輪,並且必須盡可能少轉動。 我有我的解決方案來做到這一點,它工作正常,但我不知道如何實際打印出 BFS 到達該解決方案所采用的路徑(即用於到達它的中間組合)。 任何幫助,將不勝感激!

class Solution {

    private static final String START = "0000";

    public int openLock(String[] deadends, String target) {
        if (target == null || target.length() == 0) return -1;
        Set<String> visited = new HashSet<>(Arrays.asList(deadends));
        Queue<String> queue = new LinkedList<>();
        int level = 0;
        queue.offer(START);

        while (!queue.isEmpty()) {
            int size = queue.size();
            for (int i = 0; i < size; i++) {
                String currentLock = queue.poll();
                if (!visited.add(currentLock)) continue;
                if (currentLock.equals(target)) return level;

                for (String nextLock : getNextStates(currentLock)) {
                    if (!visited.contains(nextLock)) queue.offer(nextLock);
                }
            }
            level++;
        }

        return -1;
    }

    private List<String> getNextStates(String lock) {
        List<String> locks = new LinkedList<>();
        char[] arr = lock.toCharArray();
        for (int i = 0; i < arr.length; i++) {
            char c = arr[i];
            arr[i] = c == '9' ? '0' : (char) (c + ((char) 1));
            locks.add(String.valueOf(arr));
            arr[i] = c == '0' ? '9' : (char) (c - ((char) 1));
            locks.add(String.valueOf(arr));
            arr[i] = c;
        }
        return locks;
    }
}

我認為你可以通過維持孩子父母的關系來實現它。

    Map<String,String> childToParent = new HashMap<String,String>();
    String currentLock = null;
    boolean found = false;
    while (!queue.isEmpty() && !found) {
        int size = queue.size();
        for (int i = 0; i < size; i++) {
            String currentLock = queue.poll();
            if (!visited.add(currentLock)) continue;
            if (currentLock.equals(target)){
                found = true;
                break;
            }
            for (String nextLock : getNextStates(currentLock)) {

                if (!visited.contains(nextLock)){
                   queue.offer(nextLock);
                   childToParent.put(nextLock,currentLock);
                  }
            }
        }
        level++;
    }
    if(!found){
     return -1;
    }
    // Printing path 
    int level = 0;
    while(childToParent.get(currentLock) != null){
        System.out.println(currentLock);
        currentLock = childToParent.get(currentLock);
        level++; 
    }
    System.out.println(currentLock);
    return level;

就像@Tarun 說的,你可以保持孩子與父母的關系。 我使用了一種更好的方法,但首先我要談談您遇到的其他問題。 第一個是你這樣做: Set<String> visited = new HashSet<>(Arrays.asList(deadends)); Arrays.asList(...)在你的情況下應該接受deadends中的每個String 所以,你應該把它改成這樣:

HashSet<String> set = new HashSet<>();
for(String s : deadends) {
    set.add(s);
}

當然,將其重命名為visited ,我只是從我接受的解決方案中復制和粘貼內容。 此外,您使用Queue的方式並沒有錯,但是如果您一次從中取出所有內容然后填充新值,不妨使用LinkedListArrayList 您應該從Queue一一接收條目,然后Queue放置較新的條目,因此您不必擔心跳過某些內容。

跟蹤您所做的移動量的更好方法是將其存儲到Queue本身中。 您存儲當前組合和到達那里所采取的步驟數量。 因此,當您找到答案時,只需返回第二個條目,即步數。 如果跳出循環,則返回 -1。 這是我接受的所有解決方案:

class Solution {

    public int openLock(String[] deadends, String target) {
        HashSet<String> set = new HashSet<>();
        for(String s : deadends) {
            set.add(s);
        }

        HashSet<String> visited = new HashSet<>();
        Queue<Pair<String, Integer>> queue = new LinkedList<>();
        queue.offer(new Pair<>("0000", 0));

        while(!queue.isEmpty()) {
            Pair<String, Integer> curr = queue.poll();

            if(set.contains(curr.first) || !visited.add(curr.first)) {
                continue;
            } else if(curr.first.equals(target)) {
                return curr.second;
            } else {
                LinkedList<String> next = next(curr.first);

                for(String s : next) {
                    queue.offer(new Pair<>(s, curr.second + 1));
                }
            }
        }

        return -1;
    }

    private LinkedList<String> next(String string) {
        LinkedList<String> ans = new LinkedList<>();
        ans.add(String.valueOf(new char[]{minus(string.charAt(0)), string.charAt(1), string.charAt(2), string.charAt(3)}));
        ans.add(String.valueOf(new char[]{plus(string.charAt(0)), string.charAt(1), string.charAt(2), string.charAt(3)}));
        ans.add(String.valueOf(new char[]{string.charAt(0), minus(string.charAt(1)), string.charAt(2), string.charAt(3)}));
        ans.add(String.valueOf(new char[]{string.charAt(0), plus(string.charAt(1)), string.charAt(2), string.charAt(3)}));
        ans.add(String.valueOf(new char[]{string.charAt(0), string.charAt(1), minus(string.charAt(2)), string.charAt(3)}));
        ans.add(String.valueOf(new char[]{string.charAt(0), string.charAt(1), plus(string.charAt(2)), string.charAt(3)}));
        ans.add(String.valueOf(new char[]{string.charAt(0), string.charAt(1), string.charAt(2), minus(string.charAt(3))}));
        ans.add(String.valueOf(new char[]{string.charAt(0), string.charAt(1), string.charAt(2), plus(string.charAt(3))}));
        return ans;
    }

    private char minus(char c) {
        return c == '0' ? '9' : (char) ((int) c - 1);
    }

    private char plus(char c) {
        return c == '9' ? '0' : (char) ((int) c + 1);
    }

    private class Pair<E, T> {
        E first;
        T second;

        Pair(E e, T t) {
            first = e;
            second = t;
        }
    }

}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM