找出唯一成对的数

博客介绍了一种利用位运算^(异或)性质解决寻找数组中唯一重复数字的问题。算法通过连续异或操作消除不重复的元素,最终得到重复的数值。代码示例展示了如何在1到1000的数组中找到重复的数字,无需额外存储空间,时间复杂度为O(n)。
摘要由CSDN通过智能技术生成

位运算^(异或) (只有1^0或者0^1才等于1,只有不一样的值做^才会等于1)

满足交换律和结合律

A^A=0(1)

A^0=A(2)

有(1)(2)可得A^A^b^c^c=b

连续做异或可以消除重复。

题目:1-1000这1000个数放在含有1001个元素的数组中,只有唯一的一个元素重复,其他均只出现一次。每个数组元素只能访问一次,设计一个算法,将它找出来;不用辅助存储空间,能否设计一个算法实现?

分析:设重复的数为k

那么1001个数有1,2...k,k...1000

(1,2...k,k,...1000)^(1,2...k...1000)=k

便求出了重复的数k。

代码实现:

(1)先用小数据量做测试,方便检测:

import java.util.Random;

int n=11;//假设有11个数

int []arr=new int[n];

for(int i=0;i<n-1;i++)

arr[i]=i+1;//给arr[0]到arr[9]分别赋值1,2...10

arr[arr.length-1]=new Random().nextInt(n+1)-1;//最后一个数随机生成

for(i=0;i<n;i++)

        System.out.println(arr[i]);//输出数组,方便与下面的x1对照,检测是否正确

int x1=0;//定义一个变量,初始化为0,

for(int i=1;i<n;i++)

        x1=x1*i;//为了实现1^2^3^...

for(int i=0;i<n;i++)

        x1=x1^arr[i];//(1^2^3...^k^...)^(1^2^3^...^k^k^...)结果为k,x1即为所求的重复值k。

System.out.println(x1);

(2)(1)实现无误后,将n换为1001即可,时间复杂度o(n)

import java.util.Random;
public class WeiYiChengDuiDeShu {
    public static void main(String args[]) {
        int n = 1001;
        int[] arr = new int[n];
        for(int i=0;i<n;i++)
            arr[i]=i+1;
        arr[arr.length-1]=new Random().nextInt(n-1)+1;//最后一个数随机生成,范围为1到10的闭区间
        for(int i=0;i<n;i++)
            System.out.println(arr[i]);
        int x1=0;
            for(int i=1;i<n;i++)
               x1=x1^i;
            for(int i=0;i<n;i++)
                x1=x1^arr[i];
            System.out.println(x1);
    }
}

#############################################################################如果可以构建辅助空间的话

 int []arr=new int[n];
       for(int i=0;i<n;i++)
           arr[i]=i+1;
       arr[n-1]=new Random().nextInt(n+1)-1;
        for(int i=0;i<n;i++)
            System.out.println(arr[i]);
       int []helper=new int[n];
       for(int i=0;i<n;i++)
          helper[arr[i]-1]++;//遍历arr[i]例如arr[0]=1 ,减一后为0,则helper[0]=helper[0]+1=1如此以后,除了重复的helper[]为2,其他的helper[]均为一,
        for(int i=0;i<n;i++)
            if(helper[i]==2)
            {System.out.print(arr[i]);
                    break;

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值