В чем разница между примерами кода? - PullRequest
6 голосов
/ 09 июля 2020

У меня есть код для «Найти недостающее целое число» в Codility

public static int solution(int[] A) {
    ArrayList<Integer> a = new ArrayList<Integer>();
    for(int i=0; i<A.length; i++) if(A[i] >= 0) a.add(A[i]);
    if(a.isEmpty()) {
        return 1;
    }
    a.sort(null);
    if(a.get(0) > 1) {
        return 1;       
    }
    for(int i=0; i<a.size()-1; i++) {
        if(a.get(i) != a.get(i+1) && a.get(i)+1 != a.get(i+1)) {
            return a.get(i)+1;
        }
    }
    return a.get(a.size()-1)+1;
}

Этот код работает для всех, кроме тестов производительности - large_1.

Это дает мне ошибку «получил 233 ожидается 40000 ".

Когда я заменяю этот код:

if(a.get(i) != a.get(i+1) && a.get(i)+1 != a.get(i+1)) 
return a.get(i) +1;

на

int a1 = a.get(i);
int a2 = a.get(i+1);
if(a1 != a2 && a1 +1 != a2) return a.get(i) +1;

или

int sub = a.get(i+1) - a.get(i);
if(sub != 0 && sub != 1) return a.get(i) +1;

, ошибок нет (Я получил оценку 100/100 при замене этой строки)

Есть ли кто-нибудь, кто может объяснить разницу?

Мне они кажутся одинаковыми.

Ответы [ 2 ]

3 голосов
/ 09 июля 2020
if(a.get(i) != a.get(i+1) && a.get(i)+1 != a.get(i+1)) 

Поскольку a - это ArrayList<Integer>, a.get(i) - это Integer, поэтому здесь вы сравниваете Integer s по идентичности.

Когда вы добавляли элементы массива в список с использованием a.add(A[i]), они были автоматически упакованы: компилятор переписал это в a.add(Integer.valueOf(A[i])).

Только Integer s в диапазоне -128..127 гарантированно кэшируются Integer.valueOf; поэтому, если значение Integer выходит за пределы этого диапазона, вы будете сравнивать Integer с одинаковыми значениями, но разными идентификаторами.

С другой стороны:

int a1 = a.get(i);    // Unboxing: int a1 = a.get(i).intValue()
int a2 = a.get(i+1);  // Unboxing: int a2 = a.get(i+1).intValue()
if(a1 != a2 && a1 +1 != a2)

a1 и a2 являются примитивами - вы распаковываете их, присваивая им int переменные - поэтому их можно сравнить по == или !=.

В вашей первой версии замените A != B с !A.equals(B) (или !Objects.equals(A, B)).

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

Ваше условие if, сравнивающее объекты Integer, которые не обращают внимания на адресное расположение объектов вместо значений. И я уверен, что вы этого не ожидаете.

Измените условие if на ниже -

if (a.get (i) .intValue ()! = A.get (i + 1) .intValue () && a.get (i) .intValue () + 1! = A.get (i + 1) .intValue ())

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...