知識點:哈希表;位運算java
給你一個整數數組 nums ,除某個元素僅出現 一次 外,其他每一個元素都恰出現 三次 。請你找出並返回那個只出現了一次的元素。算法
你的算法應該具備線性時間複雜度。 你能夠不使用額外空間來實現嗎?數組
輸入:nums = [2,2,3,2] 輸出:3 輸入:nums = [0,1,0,1,0,1,99] 輸出:99
和136題同樣,使用哈希表存儲每一個數字出現的數字,再遍歷哈希表,看誰能等於1;
很容易想到,但這樣作的壞處就是須要開闢新的空間;code
class Solution { public int singleNumber(int[] nums) { Map<Integer,Integer> map = new HashMap<>(); for(Integer i : nums){ map.put(i, map.getOrDefault(i, 0)+1); } for(Integer i: map.keySet()){ if(map.get(i) == 1) return i; } return -1; } }
時間複雜度:O(N);
空間複雜度:O(N);get
這題不能再用異或去解了,由於變成了三個沒有辦法抵消,可是想象一下,若是有三個如出一轍的數字,那這三個數字二進制相加後,全部位上要麼是0;要麼全是3的倍數;而後咱們的多餘元素,要麼加上去爲0;要麼加上去多了一個1,因此能夠依次求每位的和,而後%3,若是值爲1,那證實咱們在這位上的值爲1;不然爲0;
以下圖所示;hash
class Solution { public int singleNumber(int[] nums) { //在java中int類型是32位,咱們須要統計全部數字在某一位置的和能不能被3整除, // 若是不能被3整除,說明那個只出現一次的數字的二進制在那個位置是1……把32位所有統計完爲止 int ans = 0; for(int i = 0; i < 32; i++){ int count = 0; //統計1的個數; for(int j = 0; j < nums.length; j++){ count += (nums[j] >> i) & 1; //統計全部數在第i位上1的個數; } if(count % 3 != 0){ ans = ans | (1 << i); //其餘位不變,第i位置爲1; } } return ans; } }
時間複雜度:O(N);
空間複雜度:O(1);io
**掌握位運算的解決方法:這種題目每每要按位與、按位異或等操做;
此外還會有左移<<;右移>>等;好比說:class
a & 1 : a的其餘位全爲0,最後一位不變:即取a最後一位;
a | (1 << i) : a的其餘位不變,把a的第i位置爲1;
(a >> i) & 1 : 取出a第i位上的值;hashmap