劍指offer-數組-找出數組中重複的數字
1. 題目描述
給定一個長度爲 n 的整數數組 nums,數組中所有的數字都在 0∼n−1 的範圍內。
數組中某些數字是重複的,但不知道有幾個數字重複了,也不知道每個數字重複了幾次。
請找出數組中任意一個重複的數字。
注意:如果某些數字不在 0∼n−1 的範圍內,或數組中不包含重複數字,則返回 -1;
樣例
給定 nums = [2, 3, 5, 4, 3, 2, 6, 7]。
返回 2 或 3。
oj地址:https://www.acwing.com/problem/content/14/
2. 思路
觀察數據特徵發現,有重複的數字或沒有重複數字,且數字的範圍在【0,n-1】中(特例不在【0,n-1】再特殊處理)。那問題來了,如何利用上面特徵快速的發現重複的數字?
利用數組中數字範圍在【0,n-1】可以這樣做,因爲數組下標也是【0,n-1】,所以可將每個下標i上的數nums[i],放到nums[i]對應的下標nums[i]上,即設nums[i] = x,nums[x] = y,就是把x放在nums[x]上。至於如何放?是用交換方式,nums[i] <=>nums[x] ;交換完後 ,nums[i] = y,nums[x] = x,(可看出交換後y可能等於i,也可不等於所以i上新來的y是未知的,下面主要是依據它來判斷是否重複)至此我把數字x放在了它對應的下標中,對於交換後i上的數y,繼續重複把y放在到nums[y]上,若nums[y]已經是有nums[y]== y,那i上的y就是重複的並y一定是不等i的(現在出現了兩個y,一個在對應自己下標y上,那另一個y絕對不在對應自己的位置上咯,數組下標是唯一的)。
所以繼續將nums[i]上的數一直放在它的下標的循環條件是nums[nums[i]] != nums[i] (也就是nums[y]!= y) ,循環完後判斷y是否是等於i,不等於i說明是重複的是y,等於說明y正好在自己位置上。
class Solution {
public int duplicateInArray(int[] nums) {
int n = nums.length;
for(int i : nums){
if(i <0 || i >= n)
return -1;
}
for(int i=0;i<n;i++){
while(nums[nums[i]] != nums[i]) {
swap(nums, i, nums[i]);
}
if(nums[i] != i)
return nums[i];
}
return -1;
}
void swap(int[] arr, int x,int y){
int t = arr[x];
arr[x] = arr[y];
arr[y] = t ;
}
}