只出現一次的數字
本次題目要求爲:
給定一個非空整數數組,除了某個元素只出現一次以外,其餘每個元素均出現兩次。找出那個只出現了一次的元素。
說明:
你的算法應該具有線性時間複雜度。 你可以不使用額外空間來實現嗎?
示例 1:
輸入: [2,2,1] 輸出: 1
示例 2:
輸入: [4,1,2,1,2] 輸出: 4
在這裏提供4中解決方法:
1、使用HashSet
1 //1.0 2 public int singleNumber(int[] nums) { 3 Set<Integer> set = new HashSet<>(); 4 //遍歷數組,把其中的值寫入set中 5 for (int a : nums) { 6 if (!set.add(a)) { 7 //若set中已有重複值,就把該值刪除,這樣遍歷結束後的值便是唯一值 8 set.remove(a); 9 } 10 } 11 return set.iterator().next(); 12 }
2、先將傳入的數組排序,再處理
1 //2.0 2 public int singleNumber(int[] nums) { 3 Arrays.sort(nums);//對數組進行排序 4 //因爲排好序後的數組中的元素除了要尋找的那個值以外,都是成對出現的, 5 //所以,以每次遞增2的規律遍歷數組 6 for (int i = 0; i < nums.length - 1; i+=2) { 7 //當前值與它後面的值不相等,則它就是尋找值 8 if (nums[i] != nums[i + 1]) { 9 return nums[i]; 10 } 11 12 } 13 //遍歷結束後,沒有找到尋找值,則它位於數組末尾, 14 //只有這一種情況下,遍歷纔會找不到該值 15 return nums[nums.length - 1]; 16 17 }
3、分析一下這個場景下的數組,有一個規律,即我們要尋找的值在數組中的索引總是偶數,這樣我們用數組中偶數下標的和減去奇數下標的和,差值就是答案
1 //3.0 2 public int singleNumber(int[] nums) { 3 int num = 0; 4 Arrays.sort(nums);//對數組排序 5 for (int i = 0; i < nums.length; i++) { 6 //通過i%2這個運算來判斷當前元素是奇數位還是偶數位,只有爲偶數位時運算值才爲0 7 //若元素是偶數位,則num加上它的值,否則減去它的值 8 num = (i % 2 == 0) ? num + nums[i] : num - nums[i]; 9 } 10 return num; 11 }
4、回憶一下異或運算(^)的規則,參與運算的兩個數的值不一致時返回1,否則返回0,另外,0與任何數(a)異或的結果都爲它本身(a),利用這個特性,完成算法
1 //4.0 2 public int singleNumber(int[] nums) { 3 int result = 0; 4 for (int num : nums) { 5 //因爲0與任何數異或的結果都是它本身,不會影響結果,所以算法入口, 6 //我們讓0與第一個值異或,來開啓下面的運算 7 result = num ^ result; 8 } 9 return result; 10 11 }
測試方法:
1 package onceTime; 2 3 /** 4 * 5 * @author Cone 6 * @since 2019年4月21日 7 * 8 */ 9 public class TestSolution { 10 11 public static void main(String[] args) { 12 13 Solution solution = new Solution(); 14 int[] a = new int[] { 15 4,1,2,1,2 16 }; 17 System.out.println(solution.singleNumber(a)); 18 19 } 20 21 }
總結
以上四種方法,最後一種算法我個人是最喜歡的,它巧妙的運用了異或運算,JDK提供的排序算法確實好用,但是我更想實現自己的方法,對,自己造輪子。