leetcode每日刷题之数组篇(一)


题目

给定一个非空整数数组,除了某个元素只出现一次以外,其余每个元素均出现了三次。找出那个只出现了一次的元素。
示例:示例 1:

输入: [2,2,3,2]
输出: 3
示例 2:

输入: [0,1,0,1,0,1,99]
输出: 99

一、做题思路

刚看到这个题目的时候第一印象是用Hashmap来记录数字出现的次数,然后再找出出现一次的那个数。通过阅读别人的题解又学会了一些其他方法,下面我们来一块学习一下吧.
目前该题:学会了三种方法

1.Hashset

2.Hashmap

3.位运算

二、代码详解

1.HashSet

基本思路:该方法遍历一遍数组并对数组求和的同时将HashSet没有出现的数字存到哈希表里面,这样哈希表里所有在数组里出现的数都存了一遍(包括只出现一次的数)。设sum为数组的和,Hashsum为一遍的和,那么(3*Hashsum-sum)/2则为只出现一次的那个数。

class Solution {
    
    
    public int singleNumber(int[] nums) {
    
    
       HashSet<Integer> set = new HashSet<>();
        long sum=0;
        long  hashsum=0;
        for (int m: nums) {
    
    
            sum+=m;//求出数组总和
            if(set.contains(m)){
    
    
                continue;
            }
            else
            {
    
    
                hashsum+=m;
                set.add(m);//求出Hash表的和
            }
        }

        return (int)((3 * hashsum - sum) / 2);
         
    }
}

该方法易于理解,需要注意的是我们需要定义long变量,不可以int,这么做是为了防止溢出,因为int是32位整数。

2.Hashmap

基本思路:就是通过Hashmap来存储数字出现的次数,这里面的key为数组里的数字,value为出现的次数。知道这个就容易理解一些了。

class Solution {
    
    
    public int singleNumber(int[] nums) {
    
    
    
       HashMap<Integer,Integer> Hampmaptest= new HashMap<>();
       /*遍历数组,并将数字存储到Hash表中,m为key,1,2,3为value
       Sites.put(1, "Google");菜鸟教程的一个例子
       getOrDefault函数的含义是,如果没出现过就默认设置为0如果存在就获取其值*/
        for (int m: nums) {
    
    
           Hampmaptest.put(m,Hampmaptest.getOrDefault(m,0)+1);
        }
        //遍历哈希表,并查出值为1的key。输出该key
        for (int h : Hampmaptest.keySet()) {
    
    
            if(Hampmaptest.get(h)==1){
    
    
                return h;
            }
        }
   return -1;         
    }
}

3.位运算

基本思想:该方法通过位运算获取值,这个方法比较高级,看到的时候大吃一惊,我们先来举个简单的例子
[1,1,1,3]我们需要找出这里面只出现一次的数字。我们首先将他们换成二进制
0001
0001
0001
0011
我们可以看到倒数第一位1的个数为3的倍数,第二位1的个数不为3的倍数,我们想一下只要是出现三次的数,他们每一位为0或1,那么我们所以他们每一位1的个数和肯定为3的倍数。

class Solution {
    
    
    public int singleNumber(int[] nums) {
    
    
        int res = 0;
      //int型为32位
      for(int i=0;i<32;i++){
    
    
          int count=0;
           //遍历数组里的每一个数
          for (int j = 0; j < nums.length; j++) {
    
    
              //右移i为,并得出最后一位的数
              // x&1可以得出最后一位的数
              if((nums[j]>>>i&1)==1){
    
    
                  //统计该位1的个数
                  count++;
              }         
          }
          //找出1的个数不为3的倍数的位,并在尾部添加1,将其移动到原来位置
          //res |  1代表的意思是在尾部添加1.
          if(count % 3!=0){
    
    
              res = res | 1 << i;
          }
      }
      return res;
         
    }
}

4.逻辑运算符和0,1的关系

下面我总结一下各个逻辑运算符和1或0计算的作用
x | 0 :仍然是他本身
x & 0 :不论奇偶都会变成0
x ^ 0 :还是它本身
x | 1 :奇数的话,还是它本身,偶数的话则加一
x & 1:得出最后一位是0还是1,可以用来判断奇偶
x ^ 1 :如果是偶数则加一,如果是奇数则减一
参考学习链接
作者:windliang
链接:https://leetcode-cn.com/problems/single-number-ii/solution/xiang-xi-tong-su-de-si-lu-fen-xi-duo-jie-fa-by–31/

猜你喜欢

转载自blog.csdn.net/tan45du_yuan/article/details/108658559