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

一、题目
————————————————
在一个长度为n的数组里的所有数字都在0到n-1的范围内。数组中某些数字是重复的,但不知道有几个数字重复了,也不知道每个数字重复了几次。请找出数组中任意一个重复的数字。例如,如果输入长度为7的数组{2, 3, 1, 0, 2, 5, 3},那么对应的输出是重复的数字2或者3。
————————————————
二、思路
————————————————
  从哈希表的思路拓展,重排数组:把扫描的每个数字(如数字m)放到其对应下标(m下标)的位置上,若同一位置有重复,则说明该数字重复。
————————————————
三、解决问题
————————————————
测试用例
  1.数组中带一个或多个重复数字
  2.数组中不包含重复的数字
  3.无效输入测试用例(空数组,数组数字越界等)
————————————————

package swordoffer;

/**
 * @author LQ
 * @version 1.0
 * @date 2020-03-12 22:55
 */

import java.util.HashMap;
import java.util.Map;

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

public class Solution05 {
    public static void main(String[] args) {
        System.out.println("==============================");
        Solution05 sword = new Solution05();
        sword.test1();
        System.out.println("==============================");
        sword.test2();
        System.out.println("==============================");
        sword.test3();
        System.out.println("==============================");
        sword.test4();
        System.out.println("==============================");

    }
    /**
     * 方法一:时间复杂度 O(N),空间复杂度 O(1)
     * 从哈希表的思路拓展,重排数组:
     * 把扫描的每个数字(如数字m)放到其对应下标(m下标)的位置上,
     * 若同一位置有重复,则说明该数字重复。
     * 找到数组中一个重复的数字
     * 返回-1代表无重复数字或者输入无效
     */
    public int getDuplicate01(int[] array) {
        if(null == array || array.length <= 0){
            System.out.println("数组输入无效!");
            return -1;
        }
        //保证数组在一个长度为n的数组里的所有数字都在0到n-1的范围内。
        for(int arr : array){
            if(arr < 0 || arr > array.length - 1){
                System.out.println("数组大小超出范围!");
                return -1;
            }
        }
        //把扫描的每个数字(如数字m)放到其对应下标(m下标)的位置上,
        //若同一位置有重复,则说明该数字重复。
        for (int i = 0; i < array.length; i++) {
            int temp;
            while (array[i] != i){
                if (array[array[i]] == array[i]){
                    return array[i];
                }
                //交换元素
                temp = array[i];
                array[i] = array[temp];
                array[temp] = temp;
            }
        }
        System.out.println("数组中无重复数字!");
        return -1;
    }

    /**
     * 方法二:时间复杂度 O(N),空间复杂度 O(N)
     * 根据HashMap - 键值唯一的特性解题
     * @param nums
     * @return
     */
    public int getDuplicate02(int[] nums) {
        if(null == nums || nums.length <= 0){
            System.out.println("数组输入无效!");
            return -1;
        }
        //HashMap - 键值唯一 key为数字  value为出现次数
        Map<Integer, Integer> numsMap = new HashMap<>();
        int index = -1;
        for (int i = 0; i < nums.length; i++) {
            //保证数组在一个长度为n的数组里的所有数字都在0到n-1的范围内。
            if (nums[i] < 0 || nums[i] > nums.length - 1) {
                System.out.println("数组大小超出范围!");
                return -1;
            } else if (numsMap.containsKey(nums[i])) {
                //boolean containsKey(Object key)
                //如果此映射包含对于指定键的映射关系,则返回 true:已包含则返回该索引-即在原数组中的位置
                index = i;
            } else {
                //不包含,将该值放入HashMap的键
                numsMap.put(nums[i], 1);
            }
        }
        //nums[index] -- 依据index找到原数组中的元素
        return index == -1 ? -1 : nums[index];
    }
    // ==================================测试代码==================================
    /**
     *数组为null
     */
    public void test1() {
        System.out.println("test1:");
        int[] a = null;
        System.out.println("方法一:");
        int dup = getDuplicate01(a);
        if (dup >= 0){
            System.out.println("重复数字为:" + dup);
        }
        System.out.println("方法二:");
        dup = getDuplicate02(a);
        if (dup >= 0){
            System.out.println("重复数字为:" + dup);
        }
    }

    /**
     *数组无重复数字
     */
    public void test2() {
        System.out.println("test2:");
        int[] a = { 0, 1, 2, 3 };
        System.out.println("方法一:");
        int dup = getDuplicate01(a);
        if (dup >= 0){
            System.out.println("重复数字为:" + dup);
        }
        System.out.println("方法二:");
        dup = getDuplicate02(a);
        if (dup >= 0){
            System.out.println("重复数字为:" + dup);
        }
    }

    /**
     *数组数字越界
     */
    public void test3() {
        System.out.println("test3:");
        int[] a = { 1, 2, 3, 4 };
        System.out.println("方法一:");
        int dup = getDuplicate01(a);
        if (dup >= 0){
            System.out.println("重复数字为:" + dup);
        }
        dup = 0;
        System.out.println("方法二:");
        dup = getDuplicate02(a);
        if (dup >= 0){
            System.out.println("重复数字为:" + dup);
        }
    }

    /**
     *数组带重复数字
     */
    public void test4() {
        System.out.println("test4:");
        int[] a = { 1, 2, 3, 2, 4 };
        System.out.println("方法一:");
        int dup = getDuplicate01(a);
        if (dup >= 0){
            System.out.println("重复数字为:" + dup);
        }
        dup = 0;
        System.out.println("方法二:");
        dup = getDuplicate02(a);
        if (dup >= 0){
            System.out.println("重复数字为:" + dup);
        }
    }
}

图片说明
努力也是需要学习的,别再让你的努力,只感动了自己!愿你的每一次努力,都能为自己和别人创造价值。

Java基础 文章被收录于专栏

建立本人的Java基础技术栈积累库

全部评论

相关推荐

不愿透露姓名的神秘牛友
10-12 10:48
已编辑
秋招之苟:邻居家老哥19届双2硕大厂开发offer拿遍了,前几天向他请教秋招,他给我看他当年的简历,0实习实验室项目技术栈跟开发基本不沾边😂,我跟他说这个放在现在中厂简历都过不了
点赞 评论 收藏
分享
点赞 收藏 评论
分享
牛客网
牛客企业服务