找重复数字问题

这是两道面试题,我觉着很有意思。题目本身并不难,只是思路的问题。

题目1:
现有0-99共100个整数,各不相同,将所有的数放入一个数组,随机排布。
数组长度101,多余的数字是0到99其中任意一个数,将重复数字找出。
解决方案:
暴力迭代那种方式就不说了,这里提供两种比较好的方式:
public class Algo1
{
    public static void main(String[] args)
    {
        int[] arr = new int[101];
        create(arr);//构建乱序数组
        
        method1(arr);
        method2(arr);
        
        for(int i = 0; i < arr.length; i++)
        {
            System.out.print(arr[i] + " ");
        }
        
    }
    
    /**
     * 方案1:
     * 题目中指明了0~99这99个数是肯定会出现的,那么很简单,只要我们遍历数组,然后求和,将和减去0累加到99的和,之差即为重复的数
     */
    public static void method1(int[] arr)
    {
        int sum = 0;
        for(int i = 0; i < arr.length; i++)
        {
            sum += arr[i];
        }
        int constant = 0;
        for(int j = 0; j < 100; j++)
        {
            constant += j;
        }
        
        int value = sum - constant;
        System.out.println("重复数字为:"+value);
    }
    
    /**
     * 方案2:
     * 可以利用异或运算的特性: a^b^b = a  
     * 即一个数两次异或另一个数还等于这个数本身
     * --------------------------
     * 只要我们遍历数组,让第一个数与后面所有数异或,将结果再依次与0~99所有数异或结果即为重复的数
     */
    public static void method2(int[] arr)
    {
        for(int i = 1; i < arr.length; i++)
        {
            arr[0] = arr[0]^arr[i];
        }
        for(int i = 0; i <= 99; i++)
        {
            arr[0] = arr[0]^i;
        }
        System.out.println("重复数字为:"+arr[0]);
    }
    /**
     * 创建题设所要求的数组
     */
    public static void create(int[] arr)
    {
        for(int i = 0; i < arr.length; i++)
        {
            arr[i] = i;
        }
        arr[100] = 93;//重复的数字
        int temp,num1,num2;
        //乱序
        for(int j = 0; j < 1000; j++)
        {
            num1 = (int) (Math.random()*101);
            num2 = (int) (Math.random()*101);
            temp = arr[num1];
            arr[num1] = arr[num2];
            arr[num2] = temp;
        }
    }
}

题目2:
 现有一个长为100的数组,里面存放0~99中的任意数字,每个数字出现一次,
 数组中的数字是乱序的,现在从中随机取出一个数字并替换成0~99中的另一个数字,
 试找到这个重复数字
解决方案:
public class Algo2
{
    public static void main(String[] args)
    {
        int[] arr = new int[100];
        create(arr);
        for(int i = 0; i < 100; i++)
        {
            System.out.print(arr[i]+" ");
        }
        System.out.println("\n");
        System.out.println("重复数字为:"+method(arr));
    }
    
    /**
     * 解决方案:
     * 构建一个和原数组大小一致的临时数组,用于记录每个索引位所代表的数据出现的次数,
     * 比如temp[5] = 2,表示5这个数字出现了两次。
     * 通过遍历一次数组即可得到结果.
     */
    public static int method(int[] arr)
    {
        int[] temp = new int[arr.length];
        for(int i = 0; i < arr.length;i++)
        {
            temp[arr[i]]++;
            if(temp[arr[i]] == 2)
            {
                return arr[i];
            } 
        }
        return -1;
    }
    
    /**
     * 构建题设所要求的数组
     */
    public static void create(int[] arr)
    {
        for(int i = 0; i < arr.length; i++)
        {
            arr[i] = i;
        }
        int num1,num2,temp;
        for(int i = 0; i < 1000; i++)
        {
            num1 = (int) (Math.random()*100);
            num2 = (int) (Math.random()*100);
            
            temp = arr[num1];
            arr[num1] = arr[num2];
            arr[num2] = temp;
        }
        do
        {
            num1 = (int) (Math.random()*100);
            num2 = (int) (Math.random()*100);
        }while(num1 == num2);
        
        arr[num1] = arr[num2];
        System.out.println("重复数字为:"+arr[num1]);
    }
    
    
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值