LeetCode1: Single Number

1、一个非空整数数组,除了一个元素只出现一次,其余元素都出现了两次。找出这个一单独出现的元素。
note: 线性的时间复杂度,空间复杂度。

思路:第一时间想到了 Map 的 contains。以前做过一点点题,用到过,所以第一时间就想到了它。但也仅仅是想到,模模糊糊的。写的时候有想到了 ArrayList,感觉 ArrayList 要比 Map 好一些。于是就开始写了。

class Solution {
    public int singleNumber(int[] nums) {
       ArrayList list = new ArrayList<>();
        for (int i : nums) {
            if (list.contains(i)) {
                list.remove(i);
            } else {
                list.add(i);
            }
        }
        return list.get(0);
    }
}

然后检验,然后报错。

Exception in thread "main" java.lang.IndexOutOfBoundsException: Index: 2, Size: 1
    at java.util.ArrayList.rangeCheck(ArrayList.java:614)
    at java.util.ArrayList.remove(ArrayList.java:453)
    at Solution.singleNumber(Solution.java:6)
    at __Driver__.main(__Driver__.java:21)

这里不想 AndroidStudio 那样明确的指出了哪一行报错,可以点击定位,于是马虎的没有发现。纠结了好一会儿。发现是 list.remove(i);的错。看了下源码,发现不是我像当然的移除此元素,而是移除此位置上的元素。没想到这里又想当然了,发现了两个 remove 方法。

/**
     * Removes the element at the specified position in this list.
     * Shifts any subsequent elements to the left (subtracts one from their
     * indices).
     *
     * @param index the index of the element to be removed
     * @return the element that was removed from the list
     * @throws IndexOutOfBoundsException {@inheritDoc}
     */
    public E remove(int index) {
        if (index >= size)
            throw new IndexOutOfBoundsException(outOfBoundsMsg(index));

        modCount++;
        E oldValue = (E) elementData[index];

        int numMoved = size - index - 1;
        if (numMoved > 0)
            System.arraycopy(elementData, index+1, elementData, index,
                             numMoved);
        elementData[--size] = null; // clear to let GC do its work

        return oldValue;
    }

    /**
     * Removes the first occurrence of the specified element from this list,
     * if it is present.  If the list does not contain the element, it is
     * unchanged.  More formally, removes the element with the lowest index
     * i such that
     * (o==null ? get(i)==null : o.equals(get(i)))
     * (if such an element exists).  Returns true if this list
     * contained the specified element (or equivalently, if this list
     * changed as a result of the call).
     *
     * @param o element to be removed from this list, if present
     * @return true if this list contained the specified element
     */
    public boolean remove(Object o) {
        if (o == null) {
            for (int index = 0; index < size; index++)
                if (elementData[index] == null) {
                    fastRemove(index);
                    return true;
                }
        } else {
            for (int index = 0; index < size; index++)
                if (o.equals(elementData[index])) {
                    fastRemove(index);
                    return true;
                }
        }
        return false;
    }

一个是移除当前位置的元素,一个是移除此元素。第一反应懵了一下, intInteger 的区别这时出现了。根据这两种方法,可修改为:

list.remove(list.indexOf(i));
list.remove(Integer.valueOf(i));

真的是越简单约不简单啊。

最优解:位运算

class Solution {
    public int singleNumber(int[] nums) {
        int ans = 0;
        for (int i : nums) {
            ans ^= i;
        }
        return ans;
    }
}

你可能感兴趣的:(LeetCode1: Single Number)