剑指Offer面试题:1.找出数组中重复的数字

一、题目

在一个长度为n的数组里的所有数字都在0到n-1的范围内。数组中某些数字是重复的,但不知道有几个数字重复了,也不知道每个数字重复了几次。请找出数组中任意一个重复的数字。例如,如果输入长度为7的数组{2, 3, 1, 0, 2, 5, 3},那么对应的输出是重复的数字2或者3。

二、思路

算法1
将当前位置的数值放到他的位置上去,比如{2,2,3,3,4},将nums[0]的数应该放到nums[2]上,即将该数组放到他在数组中和他角标相等的位置,每次都检查要交换的位置上的数值是否一样,如果一样,则重复,如果不一样,则交换。

算法2
用hashset的add方法,如果哈希表中没有这个数据,则返回true并加入,如果有,则返回false
时间复杂度分析:o(n)

三、解决问题

3.1 代码实现

/**
     * 找到数组中一个重复的数字
     * 返回-1代表无重复的数字或者输入无效
     * 
     * 将当前位置的数值放到他的位置上去,比如{2,2,3,3,4},
     * 将nums[0]的数应该放到nums[2]上,
     * 即将该数组放到他在数组中和他角标相等的位置,
     * 每次都检查要交换的位置上的数值是否一样,
     * 如果一样,则重复,如果不一样,则交换。
     */
    public int getDuplicate(int[] arr){
        if (null == arr || arr.length <= 0){
            System.out.println("数组输入无效!");
            return -1;
        }
        for (int num : arr){
            //在一个长度为n的数组里的所有数字都在0到n-1的范围内
            if (num < 0 || num > arr.length - 1){
                System.out.println("数字大小超出范围!");
                return -1;
            }
        }
        //时间复杂度 O(N),空间复杂度 O(1)
        for (int i = 0; i < arr.length; i++) {
            while (arr[i] != i){
                // 即将该数组放到他在数组中和他角标相等的位置,
                if (arr[i] == arr[arr[i]]){
                    return arr[i];
                }
                // 交换arr[arr[i]]和arr[i]
                int temp = arr[i];
                arr[i] = arr[temp];
                arr[temp] = temp;
            }
        }
        System.out.println("数组中无重复数字!");
        return -1;
    }

    /**
     * 用hashset的add方法,如果哈希表中没有这个数据,则返回true并加入,如果有,则返回false
     * @param arr
     * @return
     */
    public int getDuplicate1(int[] arr){
        if (null == arr || arr.length <= 0){
            System.out.println("数组输入无效!");
            return -1;
        }
        for (int num : arr){
            //在一个长度为n的数组里的所有数字都在0到n-1的范围内
            if (num < 0 || num > arr.length - 1){
                System.out.println("数字大小超出范围!");
                return -1;
            }
        }
        //时间复杂度 O(N),空间复杂度 O(1)
        Set<Integer> set = new HashSet<>();
        Arrays.sort(arr);
        for (int i = 0; i < arr.length; i++) {
            //  boolean add(E e)  如果 set 中尚未存在指定的元素,则添加此元素(可选操作)。
            if (!set.add(arr[i])){
                return arr[i];
            }
        }
        System.out.println("数组中无重复数字!");
        return -1;
    }

3.2 单元测试

1.数组中带一个或多个重复数字

2.数组中不包含重复的数字

3.无效输入测试用例(空数组,数组数字越界等)

package SwordOffer;

import org.junit.Test;

import java.util.Arrays;
import java.util.HashSet;
import java.util.Set;

/**
 * @author kankan
 * @creater 2019-10-24 8:57
 * 题目:在一个长度为n的数组里的所有数字都在0到n-1的范围内。数组中某些数字是重复的,但不知道有几个数字重复了,
 * 也不知道每个数字重复了几次。请找出数组中任意一个重复的数字。例如,如果输入长度为7的数组{2, 3, 1, 0, 2, 5, 3},
 * 那么对应的输出是重复的数字2或者3。
 *
 *
 *
 */
public class Solution2 {
    /**
     * 找到数组中一个重复的数字
     * 返回-1代表无重复的数字或者输入无效
     *
     * 将当前位置的数值放到他的位置上去,比如{2,2,3,3,4},
     * 将nums[0]的数应该放到nums[2]上,
     * 即将该数组放到他在数组中和他角标相等的位置,
     * 每次都检查要交换的位置上的数值是否一样,
     * 如果一样,则重复,如果不一样,则交换。
     */
    public int getDuplicate(int[] arr){
        if (null == arr || arr.length <= 0){
            System.out.println("数组输入无效!");
            return -1;
        }
        for (int num : arr){
            //在一个长度为n的数组里的所有数字都在0到n-1的范围内
            if (num < 0 || num > arr.length - 1){
                System.out.println("数字大小超出范围!");
                return -1;
            }
        }
        //时间复杂度 O(N),空间复杂度 O(1)
        for (int i = 0; i < arr.length; i++) {
            while (arr[i] != i){
                // 即将该数组放到他在数组中和他角标相等的位置,
                if (arr[i] == arr[arr[i]]){
                    return arr[i];
                }
                // 交换arr[arr[i]]和arr[i]
                int temp = arr[i];
                arr[i] = arr[temp];
                arr[temp] = temp;
            }
        }
        System.out.println("数组中无重复数字!");
        return -1;
    }

    /**
     * 用hashset的add方法,如果哈希表中没有这个数据,则返回true并加入,如果有,则返回false
     * @param arr
     * @return
     */
    public int getDuplicate1(int[] arr){
        if (null == arr || arr.length <= 0){
            System.out.println("数组输入无效!");
            return -1;
        }
        for (int num : arr){
            //在一个长度为n的数组里的所有数字都在0到n-1的范围内
            if (num < 0 || num > arr.length - 1){
                System.out.println("数字大小超出范围!");
                return -1;
            }
        }
        //时间复杂度 O(N),空间复杂度 O(1)
        Set<Integer> set = new HashSet<>();
        Arrays.sort(arr);
        for (int i = 0; i < arr.length; i++) {
            //  boolean add(E e)  如果 set 中尚未存在指定的元素,则添加此元素(可选操作)。
            if (!set.add(arr[i])){
                return arr[i];
            }
        }
        System.out.println("数组中无重复数字!");
        return -1;
    }
    /**
     *数组带重复数字
     */
    @Test
    public void test1() {
        System.out.print("test1:");
        int[] a = { 1, 2, 3, 2, 4 };
        int dup = getDuplicate1(a);
        if (dup >= 0)
            System.out.println("重复数字为:" + dup);
    }
    /**
     *数组为null
     */
    @Test
    public void test2() {
        System.out.print("test2:");
        int[] a = null;
        int dup = getDuplicate(a);
        if (dup >= 0)
            System.out.println("重复数字为:" + dup);
    }
    /**
     *数组无重复数字
     */
    @Test
    public void test3() {
        System.out.print("test3:");
        int[] a = { 0, 1, 2, 3 };
        int dup = getDuplicate(a);
        if (dup >= 0)
            System.out.println("重复数字为:" + dup);
    }

    /**
     *数组数字越界
     */
    @Test
    public void test4() {
        System.out.print("test4:");
        int[] a = { 1, 2, 3, 4 };
        int dup = getDuplicate(a);
        if (dup >= 0)
            System.out.println("重复数字为:" + dup);
    }

}

努力也是需要学习的,别再让你的努力,只感动了自己!愿你的每一次努力,都能为自己和别人创造价值。
剑指Offer面试题:1.找出数组中重复的数字_第1张图片

你可能感兴趣的:(剑指offer题解笔记)