zoukankan      html  css  js  c++  java
  • 只出现一次的数字-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;
    }
    
  • 相关阅读:
    Visual Studio调试提示未能找到路径 bin oslyncsc.exe
    泛型
    Java中System.setProperty()
    jQuery的基础·知识
    移动端事件与touch.js库(js)
    js中,求1~100之间的质数
    匿名函数,闭包与ajax(js)
    正则(js)
    面向对象的概念,创建,实例,call与apply,继承(js)
    事件基础,事件绑定,DOM事件流与事件的默认行为,键盘事件,滚轮事件,事件委托(js)
  • 原文地址:https://www.cnblogs.com/cosefy/p/13070162.html
Copyright © 2011-2022 走看看