剑指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基础技术栈积累库