只出现一次的数字-LeetCode算法详细分析

题目:只出现一次的数字

给定一个非空整数数组,除了某个元素只出现一次以外,其余每个元素均出现两次。找出那个只出现了一次的元素。
说明:
你的算法应该具有线性时间复杂度。 你可以不使用额外空间来实现吗?

示例 1:

输入: [2,2,1]
输出: 1

示例 2:

输入: [4,1,2,1,2]
输出: 4
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;

/**
 * @author cosefy
 * @date 2020/6/8
 */
public class SingleNumber {
    public static void main(String[] args) {
        int[] nums = {24,45,1,24,1};

        int num1 = singleNumber_Test1(nums);
        int num2= singleNumber_Test2(nums);
        int num4= singleNumber_Test4(nums);

        System.out.println(num1+" "+num2+" "+num4);
    }
}   
解法一:哈希表辅助求解

思路:利用哈希表来记录数组中元素出现个数,key值记录数值大小,value记录出现次数,然后遍历哈希表得到出现次数为1的数值
分析:虽然时间复杂度为O(n),但是由于哈希表的添加元素以及哈希表的遍历,时间效率不是很高。
易错点
-注意一次循环中迭代器不能用两次next方法,否则会出现NoSuchElementException异常
-注意常见错误
思考
-考虑哈希表本方法是否存在改进的可能
-思考没有辅助空间的解决方法

public static int singleNumber_Test1(int[] nums) {
    // char[] n =  int[nums.length/2+1];
    if(nums.length%2 ==0)
        return -1;
    HashMap<Integer, Integer> map = new HashMap<>();
    for (int num : nums) {
        if (!map.containsKey(num))
            map.put(num, 1);
        else {
            Integer integer = map.get(num);
            map.put(num, integer + 1);
        }
    }
    Iterator<Integer> it = map.keySet().iterator();//此处也可用增强for循环来遍历
    while (it.hasNext()) {
        int key = it.next();
        //System.out.println("key:" + key + "Value: " + map.get(key));
            if(map.get(key)==1)
                return key;
    }
    //此处while循环中若一次循环里用到两次next方法,会抛出NoSuchElementException异常

    throw new IllegalArgumentException("不存在单个数值");
}
解法二:列表辅助实现

思路 :将数组中的元素存放到列表中,若存放相同元素,则将该元素移除,最后列表只剩下单个元素。
分析:这里同样借助了辅助空间,空间复杂度为O(n),时间复杂度O(n)

public static int singleNumber_Test2(int[] nums) {
    if(nums.length%2 ==0)
        return -1;
    ArrayList<Integer>list = new ArrayList<>();
    for (int num : nums) {
        if(!list.contains(num)) {
            list.add(num);
        }
        else {
            list.remove(list.indexOf(num));
        }
    }
    return list.get(0);

}
解法三:set辅助实现

思路:利用set元素不重合的特性,将所有不重合元素求和为sum1,数组所有元素求和为sum2,sum1*2-sum2即为单个元素值。
分析:空间复杂度为O(n),时间复杂度为O(n),过程简单

过程较为简单,不再单独书写

解法四:利用异或方法(无需辅助空间)

思路:异或操作的特点是相同元素直接异或为0,而0和任一元素异或得到任一元素自身,并且满足交换律。所以适合本题的解法
分析:时间复杂度为O(n),空间复杂度为O(1)

Javapublic static int singleNumber_Test4(int[] nums){
    if(nums.length==1)
        return nums[0];
    if(nums.length%2==0)
        return -1;
    int res = nums[0];
    for (int i = 1; i < nums.length; i++) {
        res = res ^ nums[i];
    }
    return res;
}
posted @ 2020-06-09 06:54  cosefy  阅读(116)  评论(0编辑  收藏  举报