Получение NPE из метода .equals () класса String. Как отладить это - PullRequest
2 голосов
/ 10 июля 2020

Я пытался решить 752-ю проблему LeetCode (Open the Lock) с помощью BFS. Теперь, после опроса из очереди, когда я использую переменную (тип String), чтобы приравнять ее к целевой String в условии if, я получаю NPE.

    public int openLock(String[] deadends, String target) {
        int len = target.length();
        Set <String> s = new HashSet <String> (Arrays.asList(deadends));
        Queue <String> q = new LinkedList <>();
        q.add("0000");s.add("0000");
        int cnt = 0; 
        while(!q.isEmpty()){
            int size = q.size();
            while(size>0){
                String ans = q.poll(); String t="";
                if(ans.equals(target))
                    return cnt;
                if(s.contains(ans))
                    continue;
                for(int i=len-1;i>=0;i--){
                    t=ans; char c = t.charAt(i);
                    if(c==target.charAt(i))
                        continue;
                    int act = c-'0';
                    int inc = (act+1)%10;
                    int dec = (act-1); 
                    if(dec<0)
                        dec=dec+10;
                    t=t.substring(0,i)+inc+t.substring(i+1); 
                    if(!s.contains(t)){
                        s.add(t);
                        q.add(t);
                    } 
                    t=ans;
                        t=t.substring(0,i)+dec+t.substring(i+1); 
                    if(!s.contains(t)){
                        s.add(t);
                        q.add(t);
                    } 
                }size--;
            }
            cnt++; 
        }
        return -1;
    }
} 

Ответы [ 2 ]

1 голос
/ 10 июля 2020

Не уверен в вашей ошибке, но это пройдет:

public class Solution {
    public static final int openLock(String[] deadends, String target) {
        Set<String> startSet = new HashSet<>();
        Set<String> endSet = new HashSet<>();
        Set<String> deadSet = new HashSet<>(Arrays.asList(deadends));
        startSet.add("0000");
        endSet.add(target);
        int minTurns = 0;
        Set<String> tempSet;

        while (!startSet.isEmpty() && !endSet.isEmpty()) {
            if (startSet.size() > endSet.size()) {
                tempSet = startSet;
                startSet = endSet;
                endSet = tempSet;
            }

            tempSet = new HashSet<>();

            for (String start : startSet) {
                if (endSet.contains(start))
                    return minTurns;
                }

                if (deadSet.contains(start)) {
                    continue;
                }

                deadSet.add(start);
                StringBuilder startSB = new StringBuilder(start);

                for (int i = 0; i < 4; i++) {
                    char character = startSB.charAt(i);
                    String s1 = startSB.substring(0, i) + (character == '9' ? 0 : character - '0' + 1) + startSB.substring(i + 1);
                    String s2 = startSB.substring(0, i) + (character == '0' ? 9 : character - '0' - 1) + startSB.substring(i + 1);

                    if (!deadSet.contains(s1))
                        tempSet.add(s1);
                    }

                    if (!deadSet.contains(s2)) {
                        tempSet.add(s2);
                    }
                }
            }

            minTurns++;
            startSet = tempSet;
        }

        return -1;
    }
}

Вот решение LeetCode с использованием поиска в ширину:

class Solution {
    public int openLock(String[] deadends, String target) {
        Set<String> dead = new HashSet();
        for (String d: deadends) dead.add(d);

        Queue<String> queue = new LinkedList();
        queue.offer("0000");
        queue.offer(null);

        Set<String> seen = new HashSet();
        seen.add("0000");

        int depth = 0;
        while (!queue.isEmpty()) {
            String node = queue.poll();
            if (node == null) {
                depth++;
                if (queue.peek() != null)
                    queue.offer(null);
            } else if (node.equals(target)) {
                return depth;
            } else if (!dead.contains(node)) {
                for (int i = 0; i < 4; ++i) {
                    for (int d = -1; d <= 1; d += 2) {
                        int y = ((node.charAt(i) - '0') + d + 10) % 10;
                        String nei = node.substring(0, i) + ("" + y) + node.substring(i+1);
                        if (!seen.contains(nei)) {
                            seen.add(nei);
                            queue.offer(nei);
                        }
                    }
                }
            }
        }
        return -1;
    }
}

Вы можете видеть, что есть queue.offer(null);, это может быть ваша проблема.

Ссылки

Если вы готовитесь к собеседованию :

1 голос
/ 10 июля 2020

Вызов equals для любого объекта, левая сторона которого null, вызовет NullPointerException. Правая сторона не будет бросать, если это null. Таким образом, в этом случае вы можете избежать этого, поменяв местами стороны:

if(target.equals(ans))

Предполагая, что target никогда не бывает null, конечно (я предполагаю, что это не так). Вы можете обеспечить это, добавив охранник в начало метода.

if(target == null) throw new NullPointerException("Method parameter `target` should not be null")

Это по той же причине, по которой вы обычно помещаете константы String в с левой стороны, так как вам не нужно беспокоиться о том, что это null. Например,

if("MyAmazingConstant".equals(maybeNullVariable))

Или

const String MY_AMAZING_CONSTANT = "MyAmazingConstant"

if(MY_AMAZING_CONSTANT.equals(maybeNullVariable))

Или вы можете использовать что-то вроде StringUtils из Apache Commons , которое имеет множество нулевых безопасных равенств операторы. Это также будет поддерживать другие крайние случаи (например, обе стороны будут null).

Должен ли ans быть null - это другой вопрос. Поскольку вы получаете значение Queue с помощью метода poll, это означает, что Queue в это время пусто.

...