40 数组中只出现一次的(两个)数字(i与i+1的比较之后的处理---根据二进制中的 位 划分两个数组)

题目描述 一个整型数组里除了两个数字之外,其他的数字都出现了两次。请写程序找出这两个只出现一次的数字。//num1,num2分别为长度为1的数组。传出参数//将num1[0],num2[0]设置为返回结果import java.util.*;public class Solution { public void FindNumsAppearOnce(int [] array...
摘要由CSDN通过智能技术生成

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

//num1,num2分别为长度为1的数组。传出参数
//将num1[0],num2[0]设置为返回结果
import java.util.*;
public class Solution {
    public void FindNumsAppearOnce(int [] array,int num1[] , int num2[]) {
        Arrays.sort(array);
        int i = 0;
        while(i<array.length-1){
            if((array[i] ^ array[i+1]) == 0)
                i = i + 2;
            else{
                num1[0] = array[i];
                i++;
                break;
            }                
        }

        while(i<array.length-1){
            if((array[i] ^ array[i+1]) == 0)
                i = i + 2;
            else{
                num2[0] = array[i];
                break;
            }                
        }
        if(i == array.length-1)
            num2[0] = array[array.length-1];
    }
}

有一个很重要的点:如何判断一个数的二进制某一位是不是1???对1取&
对其排序后,将一个的数字保存下来!
注意:最后的判断,由于循环中存在i与i+1的比较,所以while中必须保证下面不能越界,i<array.length-1,但是i是可能取到array.length-1这个数值的。所以最后需要最其进行一个判断!
把一个混乱的数组给规则化,即对其进行排序是一个常规想法!

异或做法:
怎么实现子数组的划分呢?对原数组从头到尾进行异或,最后出现的为这两个出现一次的数异或的结果。在这个结果的二进制表示中,至少有一位为1,因为这两个数不相同。那么,从该结果中找到第一个为1的位置,该位记为从最低位开始计数的第n位。
那么,划分的标准定为:从最低位开始计数的第n位是否为1。
因为出现两次的同一个数字,各个位数上都是相同的,所以一定被分到同一个子数组中,且每个子数组中只包含一个出现一次的数字。

//num1,num2分别为长度为1的数组。传出参数
//将num1[0],num2[0]设置为返回结果
import java.util.*;
public class Solution {
    public int placeOfOne(int value){
        int n = 1;
        while((value & 1) != 1){
            n++;
            value = value >> 1;
        }
        return n;
    }
    public boolean isOne(int value,int n){
        int i = 1;
        while(i <= n){
            if((value & 1) == 1)
                return true;             
            value = value >> 1;
            i++;
        }
        return false;
    }
    public void FindNumsAppearOnce(int [] array,int num1[] , int num2[]) {
        int value = array[0];
        for(int i=1;i<array.length;i++){
            value ^= array[i];
        }
        int n = placeOfOne(value);
        ArrayList<Integer> arr1 = new ArrayList();
        ArrayList<Integer> arr2 = new ArrayList();
        for(int i=0;i<array.length;i++){
            if(isOne(array[i],n))
                arr1.add(array[i]);
            else
                arr2.add(array[i]);
        }
        num1[0] = arr1.get(0);
        for(int i=1;i<arr1.size();i++){
            num1[0] ^= arr1.get(i);
        }

        num2[0] = arr2.get(0);
        for(int i=1;i<arr2.size();i++){
            num2[0] ^= arr2.get(i);
        }
    }
}

补充:

 public boolean isOne(int value,int n){
        return((value >> n-1) & 1) == 1;  
    }

这个函数可以更简化一些,注意右移的是n-1位。
而且placeOfOne()函数中要注意,一个整数右移的次数<32,之后为0!
参考:https://blog.csdn.net/ouyangyanlan/article/details/72668012

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值