(java)剑锋Offer(找出数组中任意一个重复的数字)题目一

以下为代码实现: 

package com.example.offer;
import java.util.HashMap;

/**
 * 在一个长度为n的数组里的所有数字都在0-n-1的范围内。数组中某些数字是重复的,
 * 但是不知道有几个数字重复了,也不知道每个数字重复了多少次。
 * 找出数组中任意重复的数字
 */
public class DuplicateTest {
    public static void main(String[] args) {
        //int[] array=null; //测试空指针的情况

        int[] array={2,3,1,0,2,5,3};
        int result03=duplicateNum03(array);
        //int result02=duplicateNum02(array);
        //int result=duplicateNum(array);
        if(result03>=0){
            System.out.println("数组中重复的数字为:"+result03);
        }else{
            System.out.println("数组中不存在重复的数字");
        }

    }
    /**
     * 第一种方法,将数组进行排序,排序之后找到重复的数
     * @param array
     * @return
     */
    public static int duplicateNum(int[] array){
        //避免空指针
        if(array==null || array.length<=0){
            throw new NullPointerException("您输入的数组为空");
        }
        //避免输入的数组元素不符合要求
        for (int i = 0; i < array.length; i++) {
            if(array[i]<0 || array[i]>array.length-1){
                throw new IllegalArgumentException("您输入的数组不符合要求");
            }
        }
        int result=-1;
        //采用冒泡排序
        for (int i = 0; i < array.length-1; i++) {
            //优化:如果一轮遍历下来,没有进行任何的交换,说明数组的顺序已经排好了
            boolean flag=true;
            for (int j = 0; j < array.length-i-1; j++) {
                if (array[j]>array[j+1]){
                    int temp=0;
                    temp=array[j];
                    array[j]=array[j+1];
                    array[j+1]=temp;
                    flag=false;
                }
            }
            if(flag){
                break;
            }
        }
        //打印一下数组
        for (int num :array) {
            System.out.print(num+" ");
        }
        //查询出重复的数字
        for (int i = 0; i < array.length; i++) {
            if(array[i]==array[i+1]){
                result=array[i];
                break;
            }
        }
        return result;
    }
    /**
     * 第二种方法:采用hash表解决
     * @param array
     * @return
     */
    public static int duplicateNum02(int[] array){
        //避免空指针
        if(array==null || array.length<=0){
            throw new NullPointerException("您输入的数组为空");
        }
        //避免输入的数组元素不符合要求
        for (int i = 0; i < array.length; i++) {
            if(array[i]<0 || array[i]>array.length-1){
                throw new IllegalArgumentException("您输入的数组不符合要求");
            }
        }
        int result=-1;
        //采用hashMap实现
        HashMap<Integer,Integer> map=new HashMap();
        for (int i = 0; i < array.length; i++) {
            if(map.containsValue(array[i])){
                result=array[i];
                break;
            }else{
                map.put(array[i],array[i]);
            }
        }
        return result;
    }
    /**
     * 第三种方法:利用数组中的数字在0-n-1之间这个特性
     * 遍历这个数组,首先比较当前这个数值是否与其下标相等,如果相等则扫描下一数值
     * 如果不相等则将此数值与以此数值为下标数值进行比较,如果相等则找到相等的数字
     * 如果不相等则将两个数值进行交换
     * @param array
     * @return
     */
    public static int duplicateNum03(int[] array){
        //避免空指针
        if(array==null || array.length<=0){
            throw new NullPointerException("您输入的数组为空");
        }
        //避免输入的数组元素不符合要求
        for (int i = 0; i < array.length; i++) {
            if(array[i]<0 || array[i]>array.length-1){
                throw new IllegalArgumentException("您输入的数组不符合要求");
            }
        }
        int result=-1;
        for (int i = 0; i < array.length ; i++) {
            System.out.println("每次都打印出i值:"+i);
            while (array[i]!=i){
                if(array[i]==array[array[i]]){
                    result=array[i];
                    return result;
                }else{
                    //交换两个值
                    int temp=0;
                    temp=array[array[i]];
                    array[array[i]]=array[i];
                    array[i]=temp;
                }
            }
        }
        return result;
    }
}

 代码分析:第一种方法采用排序,时间复杂度为O(n2);第二种方法采用Hash表,我直接使用了HashMap,但是使用HashMap应该要考虑很多的底层性能问题,所以可以自己根据数组的长度模拟一个哈希表,所以第二种的时间复杂度是O(n),另外空间复杂度是O(n)。第三种,看代码的话是用到了两层循环,会认为时间复杂度为O(n2),但是每个数字最多只要交换两次就可以找到属于他的位置,所以总的时间复杂度是O(n), 空间复杂度为O(1)。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值