[LeetCode]--136. Single Number

来源:互联网 发布:端口在线扫描 编辑:程序博客网 时间:2024/06/01 21:10

Given an array of integers, every element appears twice except for one. Find that single one.

Note:
Your algorithm should have a linear runtime complexity. Could you implement it without using extra memory?

耐心看下我的思想演变过程吧,可能是大脑缺氧,用List装下标。

public int singleNumber(int[] nums) {        if (nums.length == 1)            return nums[0];        ArrayList<Integer> temp = new ArrayList<Integer>();        for (int i = 0; i < nums.length - 1; i++) {            if (temp.contains(i))                continue;            for (int j = i + 1; j < nums.length; j++) {                if (temp.contains(j))                    continue;                if (nums[i] == nums[j]) {                    System.out.println(i + "---" + j);                    temp.add(i);                    temp.add(j);                    break;                }            }        }        for (int i = 0; i < nums.length; i++) {            if (!temp.contains(i)) {                return nums[i];            }        }        return 0;    }

代码逻辑和实现应该没有问题,测试也通过了,就是提交的时候超时了,于是我就想着用空间去换取时间。

public int singleNumber1(int[] nums) {        ArrayList<Integer> preList = new ArrayList<Integer>();        ArrayList<Integer> list = new ArrayList<Integer>();        int len = nums.length;        int[] flag = new int[len];        Arrays.fill(flag, 0);        for (int i = 0; i < len; i++) {            if (!preList.contains(nums[i])) {                preList.add(nums[i]);            } else {                flag[i] = 1;            }            if (!list.contains(nums[len - 1 - i])) {                list.add(nums[len - 1 - i]);            } else {                flag[len - 1 - i] = 1;            }        }        for (int i = 0; i < flag.length; i++) {            if (flag[i] == 0) {                return nums[i];            }        }        return 0;    }

这也是一种方法其实,两头同时遍历,一次遍历就可以解决问题,但是仔细想想其实复杂度没减。

再使用暴力搜索,遍历数组,发现两个元素相等,则将这两个元素的标志位置为1,最后返回标志位为0的元素即可。时间复杂度O(n^2)没有AC,Status:Time Limit Exceed

public int singleNumber2(int[] nums) {        int n = nums.length;        if (n == 1)            return nums[0];        int[] flag = new int[n];        for (int i = 0; i < n; i++) {            if (flag[i] == 1)                continue;            else {                for (int j = i + 1; j < n; j++) {                    if (nums[i] == nums[j]) {                        flag[i] = 1;                        flag[j] = 1;                    }                }            }        }        for (int i = 0; i < n; i++) {            if (flag[i] == 0)                return nums[i];        }        return 0;    }

后来用这个就是通过的,Accept!真是高兴,但是又不服,这个其实和第一次一样,只是用数组装flag。而且我觉得很有可能是偶然通过的。

其实我记得有个位运算很简单也很高效。但是说实话,一般来说大家对位运算都有种神秘陌生对吧,我也不例外,虽然知道,但是用起来很困难。

利用异或操作。异或的性质1:交换律a ^ b = b ^ a,性质2:0 ^ a = a。于是利用交换律可以将数组假想成相同元素全部相邻,于是将所有元素依次做异或操作,相同元素异或为0,最终剩下的元素就为Single Number。时间复杂度O(n),空间复杂度O(1)

public int singleNumber(int[] A) {        if(A == null || A.length == 0) {            return -1;        }        int rst = 0;        for (int i = 0; i < A.length; i++) {            rst ^= A[i];        }        return rst;    }

所以还是强烈建议用后面这种。

0 0
原创粉丝点击