一、题目
在一个长度为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);
}
}
努力也是需要学习的,别再让你的努力,只感动了自己!愿你的每一次努力,都能为自己和别人创造价值。