本文參考自《劍指offer》一書,代碼采用Java語言。
題目
在一個長度為n的數組里的所有數字都在0到n-1的范圍內。數組中某些數字是重復的,但不知道有幾個數字重復了,也不知道每個數字重復了幾次。請找出數組中任意一個重復的數字。例如,如果輸入長度為7的數組{2, 3, 1, 0, 2, 5, 3},那么對應的輸出是重復的數字2或者3。
思路
從哈希表的思路拓展,重排數組:把掃描的每個數字(如數字m)放到其對應下標(m下標)的位置上,若同一位置有重復,則說明該數字重復。
(在動手寫代碼前應該先想好測試用例)
測試用例
1.數組中帶一個或多個重復數字
2.數組中不包含重復的數字
3.無效輸入測試用例(空數組,數組數字越界等)
完整Java代碼
(含測試代碼)
/**
* @Description 找出數組中重復的數字
*
* @author yongh
* @date 2018年7月16日 上午10:24:05
*/
/*
* 題目:在一個長度為n的數組里的所有數字都在0到n-1的范圍內。數組中某些數字是重復的,但不知道有幾個數字重復了,
* 也不知道每個數字重復了幾次。請找出數組中任意一個重復的數字。例如,如果輸入長度為7的數組{2, 3, 1, 0, 2, 5, 3},
* 那么對應的輸出是重復的數字2或者3。
*/
public class FindDuplication {
/**
* 找到數組中一個重復的數字
* 返回-1代表無重復數字或者輸入無效
*/
public int getDuplicate(int[] arr) {
if (arr == null || arr.length <= 0) {
System.out.println("數組輸入無效!");
return -1;
}
for (int a : arr) {
if (a < 0 || a > arr.length - 1) {
System.out.println("數字大小超出范圍!");
return -1;
}
}
for (int i = 0; i < arr.length; i++) {
int temp;
while (arr[i] != i) {
if (arr[arr[i]] == arr[i])
return arr[i];
// 交換arr[arr[i]]和arr[i]
temp = arr[i];
arr[i] = arr[temp];
arr[temp] = temp;
}
}
System.out.println("數組中無重復數字!");
return -1;
}
// ==================================測試代碼==================================
/**
*數組為null
*/
public void test1() {
System.out.print("test1:");
int[] a = null;
int dup = getDuplicate(a);
if (dup >= 0)
System.out.println("重復數字為:" + dup);
}
/**
*數組無重復數字
*/
public void test2() {
System.out.print("test2:");
int[] a = { 0, 1, 2, 3 };
int dup = getDuplicate(a);
if (dup >= 0)
System.out.println("重復數字為:" + dup);
}
/**
*數組數字越界
*/
public void test3() {
System.out.print("test3:");
int[] a = { 1, 2, 3, 4 };
int dup = getDuplicate(a);
if (dup >= 0)
System.out.println("重復數字為:" + dup);
}
/**
*數組帶重復數字
*/
public void test4() {
System.out.print("test4:");
int[] a = { 1, 2, 3, 2, 4 };
int dup = getDuplicate(a);
if (dup >= 0)
System.out.println("重復數字為:" + dup);
}
public static void main(String[] args) {
FindDuplication f = new FindDuplication();
f.test1();
f.test2();
f.test3();
f.test4();
}
}
test1:數組輸入無效! test2:數組中無重復數字! test3:數字大小超出范圍! test4:重復數字為:2
復雜度
時間復雜度:O(n)
空間復雜度:O(1)
====================================================================
在牛客網中提交的代碼如下(不含測試代碼):
public class Solution {
// Parameters:
// numbers: an array of integers
// length: the length of array numbers
// duplication: (Output) the duplicated number in the array number,length of duplication array is 1,so using duplication[0] = ? in implementation;
// Here duplication like pointor in C/C++, duplication[0] equal *duplication in C/C++
// 這里要特別注意~返回任意重復的一個,賦值duplication[0]
// Return value: true if the input is valid, and there are some duplications in the array number
// otherwise false
public boolean duplicate(int numbers[],int length,int [] duplication) {
if(numbers==null||length<=0)
return false;
for(int a:numbers){
if(a<0||a>=length)
return false;
}
int temp;
for(int i=0;i<length;i++){
while(numbers[i]!=i){
if(numbers[numbers[i]]==numbers[i]){
duplication[0]=numbers[i];
return true;
}
temp=numbers[i];
numbers[i]=numbers[temp];
numbers[temp]=temp;
}
}
return false;
}
}
這里有一個收獲:在Java的方法中,可以用duplication[0]代替C/C++中的指針*duplication,從而在返回boolean的同時,也可以獲得需要的數字。
