137.Single Number II

Posted 二十年后20

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了137.Single Number II相关的知识,希望对你有一定的参考价值。

题目链接:https://leetcode.com/problems/single-number-ii/description/

题目大意:给出一串数,每个数都出现三次,只有一个数只出现一次,把这个出现一次的数找出来。

法一:利用hashMap,空间换时间,但是好像也没怎么换到时间。代码如下(耗时15ms):

 1     public int singleNumber(int[] nums) {
 2         Map<Integer, Integer> map = new HashMap<Integer, Integer>();
 3         int ans = -1;
 4         for(int i = 0; i < nums.length; i++) {
 5             if(map.containsKey(nums[i])) {
 6                 map.put(nums[i], map.get(nums[i]) + 1);
 7             }
 8             else {
 9                 map.put(nums[i], 1);
10             }
11         }
12         for(int i = 0; i < nums.length; i++) {
13             if(map.get(nums[i]) == 1) {
14                 ans = nums[i];
15                 break;
16             }
17         }
18         return ans;
19     }
View Code

法二:先排序,再一一计算。代码如下(耗时5ms):

 1     public int singleNumber(int[] nums) {
 2         Arrays.sort(nums);
 3         int ans = nums[0];
 4         int cnt = 1;
 5         int length = nums.length;
 6         for(int i = 1; i < length; i++) {
 7             if(nums[i] != nums[i - 1]) {
 8                 if(cnt == 1) {
 9                     break;
10                 }
11                 ans = nums[i];
12                 cnt = 1;
13             }
14             else {
15                 cnt++;
16             }
17         }
18         return ans;
19     }
View Code

法三(借鉴):利用位运算,这个方法是普遍方法,136题也可以用这个方法做,但是时间复杂度其实是o(n^2),所以也不是最优的,只是用到了位运算。借鉴自:http://blog.csdn.net/feliciafay/article/details/19004479。代码如下(耗时7ms):

 1     public int singleNumber(int[] nums) {
 2         int ans = 0;
 3         int length = nums.length;
 4         //将每一个数取二进制位按位相加,如果都是重复的则当前位的相加和一定是3的倍数,否则当前位一定存在于要找的那个数中
 5         //比如1,1,1,2,2,2,3这六个数将其转为二进制数按位相加,然后每一位都对3取模,最后一定可以得到3
 6         for(int i = 0; i < 32; i++) {//计算每一位
 7             int sum = 0;//统计每一位的和
 8             for(int j = 0; j < length; j++) {//对每个数取第i位的数值
 9                 if(((nums[j] >> i) & 1) == 1) {//取第i位的数值
10                     sum++;//将每个数第i位的值相加求和
11                     sum %= 3;
12                 }
13             }
14             if(sum != 0) {//如果对3取模后非0,则说明当前位一定是要找的数的某一位
15                 ans |= sum << i;//将其转为十进制加入结果当中
16             }
17         }
18         return ans;
19     }
View Code

法四(借鉴):这个位运算还没看懂。https://www.cnblogs.com/yangrouchuan/p/5323327.html

 

 1 链接:https://www.nowcoder.com/questionTerminal/e02fdb54d7524710a7d664d082bb7811
 2 来源:牛客网
 3 
 4 /**
 5      * 数组中有两个出现一次的数字,其他数字都出现两次,找出这两个数字
 6      * @param array
 7      * @param num1
 8      * @param num2
 9      */
10     public static void findNumsAppearOnce(int [] array,int num1[] , int num2[]) {
11         if(array == null || array.length <= 1){
12             num1[0] = num2[0] = 0;
13             return;
14         }
15         int len = array.length, index = 0, sum = 0;
16         for(int i = 0; i < len; i++){
17             sum ^= array[i];
18         }
19         for(index = 0; index < 32; index++){
20             if((sum & (1 << index)) != 0) break;
21         }
22         for(int i = 0; i < len; i++){
23             if((array[i] & (1 << index))!=0){
24                 num2[0] ^= array[i];
25             }else{
26                 num1[0] ^= array[i];
27             }
28         }
29     }
30 /**
31      * 数组a中只有一个数出现一次,其他数都出现了2次,找出这个数字
32      * @param a
33      * @return
34      */
35     public static int find1From2(int[] a){
36         int len = a.length, res = 0;
37         for(int i = 0; i < len; i++){
38             res = res ^ a[i];
39         }
40         return res;
41     }
View Code

 

以上是关于137.Single Number II的主要内容,如果未能解决你的问题,请参考以下文章

137. Single Number II

137. Single Number II

137. Single Number II(js)

137. Single Number II

LeetCode136 Single Number, LeetCode137 Single Number II, LeetCode260 Single Number III

[leetcode-137-Single Number II]