简体   繁体   English

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

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

I'm working on a problem from Leetcode where we're given a lock combination to reach from the starting combination of 0000. You can only rotate one lock wheel at a time, and you must do it using as few turns as possible.我正在解决 Leetcode 中的一个问题,我们给出了一个锁组合,可以从 0000 的起始组合到达。您一次只能旋转一个锁轮,并且必须尽可能少转动。 I have my solution to do this, and it works fine, but I don't know how to actually print out the path that the BFS takes to reach this solution (ie the intermediary combinations used to reach it).我有我的解决方案来做到这一点,它工作正常,但我不知道如何实际打印出 BFS 到达该解决方案所采用的路径(即用于到达它的中间组合)。 Any help would be appreciated!任何帮助,将不胜感激!

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;
    }
}

I think you can accomplish it by maintaining child parent relationship.我认为你可以通过维持孩子父母的关系来实现它。

    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;

Like @Tarun said, you can keep a child to parent relationship.就像@Tarun 说的,你可以保持孩子与父母的关系。 There is a better way that I used, but first I'm going to talk about what other problems you have.我使用了一种更好的方法,但首先我要谈谈您遇到的其他问题。 The first one is you are doing this: Set<String> visited = new HashSet<>(Arrays.asList(deadends));第一个是你这样做: Set<String> visited = new HashSet<>(Arrays.asList(deadends)); Arrays.asList(...) in you're case should take in every String in deadends . Arrays.asList(...)在你的情况下应该接受deadends中的每个String So, you should change it to this:所以,你应该把它改成这样:

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

Of course rename it to visited , I'm just copy and pasting stuff from my accepted solution.当然,将其重命名为visited ,我只是从我接受的解决方案中复制和粘贴内容。 Also, the way you're using Queue is not wrong, but if you're taking everything from it at once and then stuffing new values, might as well use LinkedList or ArrayList .此外,您使用Queue的方式并没有错,但是如果您一次从中取出所有内容然后填充新值,不妨使用LinkedListArrayList You should take in entries from the Queue one by one, and the Queue puts newer entries later, so you don't have to worry about skipping over things.您应该从Queue一一接收条目,然后Queue放置较新的条目,因此您不必担心跳过某些内容。

The better method for keeping track of the amount of moves you made is storing it into the Queue itself.跟踪您所做的移动量的更好方法是将其存储到Queue本身中。 You store the current combination and the amount of steps taken to get there.您存储当前组合和到达那里所采取的步骤数量。 So, when you find you're answer, just return the second entry, the number of steps.因此,当您找到答案时,只需返回第二个条目,即步数。 If you break out of the loop, return -1.如果跳出循环,则返回 -1。 Here is my accepted solution using all of that:这是我接受的所有解决方案:

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