JAVA: 数组中只出现1次的数

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

分析:

解法一:若没有规定空间复杂度为O(1),则可以利用hashmap的特性来存储数字及其出现的次数,在对hashmap的value值进行排序,前两个key值即为所求。

public class Solution {
    //num1,num2分别为长度为1的数组。传出参数
    //将num1[0],num2[0]设置为返回结果
    public void FindNumsAppearOnce(int [] array,int num1[] , int num2[]) {
        if(array.length<=0|| array==null)   return;
        HashMap<Integer,Integer> map=new HashMap<>();
        for(int i=0;i<array.length;i++){
            if(map.containsKey(array[i])){
                int count=map.get(array[i]);
                map.put(array[i],++count);
            }else{
                map.put(array[i],1);
            }
        }
        List<Map.Entry<Integer,Integer>> list=new ArrayList<>(map.entrySet());
        Collections.sort(list, new Comparator<Map.Entry<Integer, Integer>>() {
            @Override
            public int compare(Map.Entry<Integer, Integer> o1, Map.Entry<Integer, Integer> o2) {
                return o1.getValue().compareTo(o2.getValue());
            }
        });
        num1[0]=list.get(0).getKey();
        num2[0]=list.get(1).getKey();
    }
}

解法二: 该方法时间复杂度为O(n),空间复杂度为O(1)。 

  • 利用异或的性质,任何一个数异或它自己都为0;0与任何一个数异或都为原数字。
  • 出现两次的数都被抵消掉,根据数组异或的结果求得第一个为1的下标,记为第n位。为1表示除了抵消掉的数之外,剩余的两个数在该位上不同,否则相同的话异或结果位0;
  • 按照第n位是否为1进行划分,得到两个数组,且相同数字的都划分到了一个组中,并且每个数组中都只包含一个只出现1次的数字。
  • 分别对两数组进行异或,可以得到两个只出现1次的数字。
//num1,num2分别为长度为1的数组。传出参数
//将num1[0],num2[0]设置为返回结果
public class Solution {
    public void FindNumsAppearOnce(int [] array,int num1[] , int num2[]) {
        int length=array.length;
        if(length<=0||array==null)  return;
        if(length==2){
            num1[0]=array[0];
            num2[0]=array[1];
            return;
        }
        int bitresult=0;
        //对数组中的数依次求异或
        for(int i=0;i<length;i++){
            bitresult^=array[i];
        }
        //找到异或运算结果第一个为1的位置
        int firstIndexIs1=findfirst1(bitresult);
        //按找该位置的值是否为1进行分组,并每组进行异或运算,最后的值即为只出现1次的数
        for(int i=0;i<length;i++){
            if(isBit1(array[i],firstIndexIs1)){
                num1[0]^=array[i];
            }else{
                num2[0]^=array[i];
            }
        }
    }

    private int findfirst1(int bitresult){
        int index=0;
        while((bitresult & 1)==0 && index<32){
            bitresult>>=1;
            index++;
        }
        return index;
    }

    private boolean isBit1(int target,int index){
        return ((target>>index)&1)==1;
    }
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值