一、題目
在一個長度爲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);
}
}
努力也是需要學習的,別再讓你的努力,只感動了自己!願你的每一次努力,都能爲自己和別人創造價值。