剑指Offer-38 数组中的单身贵族(位运算)

一个整型数组里除了两个数字之外,其他的数字都出现了偶数次。请写程序找出这两个只出现一次的数字。

集合法

其实,我觉得使用HashSet挺好的,时间复杂度也可以接受。
遍历数组

  1. 如果数不在集合中,添加到集合中
  2. 如果数在集合中,从集合中去掉
    遍历完成之后,数组中只剩下了两个数,也就是要求的单身数。
//num1,num2分别为长度为1的数组。传出参数
//将num1[0],num2[0]设置为返回结果
import java.util.*;

public class Solution {
    public void FindNumsAppearOnce(int [] array,int num1[] , int num2[]) {
        Set<Integer> set = new HashSet<>();
        for(Integer i : array){
            // HashSet 时间复杂度为O(1)
            if(set.contains(i)) set.remove(i);
            else set.add(i);
        }
        ArrayList<Integer> list = new ArrayList<>(set);
        num1[0] = list.get(0);
        num2[0] = list.get(1);
    }
}

位运算

这个需要对Java位运算有一定的熟悉。
异或: 1000 XOR 1101 = 0101 相同为0,不同为1
与:1000 & 1100 = 1000 同时为1 的时候为1,否则为0
对于这一题:

  1. 把所有的数字亦或一下,相同的数字亦或后全部变成了0,相当于只把两个不同的数异或了。
  2. 两个不同数字亦或结果肯定不为0,找到结果中不为0的位。
  3. 对于整个数组,根据该位是否为0分为两组。每组异或即可得到结果。
//num1,num2分别为长度为1的数组。传出参数
//将num1[0],num2[0]设置为返回结果
public class Solution {
    public void FindNumsAppearOnce(int [] array,int num1[] , int num2[]) {
        int sum = 0;
        for(int i : array) sum ^= i; // 所有数字异或
        int flag = 1; // 此时flag最低位为1
        while((sum & flag) == 0) flag <<=1; // 寻找标志位
        for(int i : array){
            if((i & flag) == 0) num1[0] ^= i; // 标志位为0组
            else num2[0] ^= i;// 标志位为1组
        }
    }
}
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

  • 数组 记录《剑指offer》中所有关于数组的题目,以及LeetCode中的相似题目 相关题目列表 说明 由于简书...
    wenmingxing阅读 1,532评论 1 12
  • 1 不是欧洲中世纪,仿若黎明前最深的夜的时代,拉丁文教义只由教士任意曲解; 不是封建明清朝,八股文阉割了思想的王朝...
    普路同阅读 299评论 1 3
  • 紧盯就是为了分享 我都快要垂涎了 那么小气 唉,等着吧! 故意逗我吧 还不给,我就要疯了 像一只小羊羔 自豪又恬雅...
    学院词人阅读 366评论 0 1
  • 把我捆绑 还让我飞翔 当我被高高的围墙阻碍 当我被撞得遍体鳞伤 不能流泪 却也没有安慰 只有鞭策和一句: 你怎么还...
    沧海踏歌世无双阅读 165评论 0 0
  • 殊不知最近是不是天气太热 ,还是事情太多,整个人仿佛跟个炸弹一般,随时随地都会被引爆!生活中大大小小的事情都可...
    淤之阅读 508评论 2 2