剑指Offer.03-数组中重复的数字
题目描述
/**
* @Author: PlusHuang
* @Date: 2021/11/23 11:23
* @Theme: 剑指Offer
* @Description:找出数组中重复的数字。
* 在一个长度为 n 的数组 nums 里的所有数字都在 0~n-1 的范围内。数组中某些数字是重复的,但不知道有几个数字重复了,
* 也不知道每个数字重复了几次。请找出数组中任意一个重复的数字。
*/
输入: [2, 3, 1, 0, 2, 5, 3] 输出:2 或 3
解答思路和参考代码
解答一
主要抓住"数组元素的数字都在0-n之间"这一点入手,可以新建有一个同一长度的数组,把原数组的每个元素的个数添加到对应下标对应的元素中,一旦出现元素大于1,停止遍历,返回当前下表,即是重复数字。
class Solution {
public int findRepeatNumber(int[] nums) {
int[] flag = new int[nums.length];
for(int i=0;i<nums.length;i++){
flag[nums[i]]++;
}
int ran = 0;
for(int i=0;i<nums.length;i++){
if(flag[i]>1){
ran = i;
break;
}
}
return ran;
}
}
解答二
同样利用这一特殊点,在不设置新数组的前提下,在原数组上将对应元素转移到对应下标上,若发现该下表对应的元素已经是改下标数值,则找到了重复数字
package d21_11_23;
/**
* @Author: PlusHuang
* @Date: 2021/11/23 11:23
* @Theme: 剑指Offer
* @Description:找出数组中重复的数字。
* 在一个长度为 n 的数组 nums 里的所有数字都在 0~n-1 的范围内。数组中某些数字是重复的,但不知道有几个数字重复了,
* 也不知道每个数字重复了几次。请找出数组中任意一个重复的数字。
*/
public class A {
public static void main(String[] args) {
int[] array=new int[]{2,3,1,0,2,5,3};
System.out.println(findRepeatNum(array));
}
public static int findRepeatNum(int[] array){
//如果数组长度为1,则返回-1,表示失败
if(array.length==1){
return -1;
}
//判断该数组的每个元素是否符合要求
for (int temp: array) {
if(temp<0||temp>array.length-1){
return -1;
}
}
//正式进入该算法
/**
* 算法思想:对于这种长度为n-1且元素值介于0~n-1的数组,可以将只为i的元素放到对应第i个位置。
*/
for (int i = 0; i < array.length; i++) {
//持续该循环直至每一个元素在其对应下标的位置上
while(array[i]!=i){//循环体里将对应元素放到对应下标处。
//判断当前这个数和以这个数为下标的数是否相等
if(array[i] == array[array[i]]){
//相等则返回这个相等的数
return array[i];
}else{
//不相等则交换这两个数
int temp = array[i];
array[i] = array[temp];
array[temp] = temp;
}
}
}
return -1;
}
}
方法总结和启示
遇到这种特殊数组的题目,一般考虑两种方法,一种是新开辟一个数组(理解容易,消耗内存),一种是在原数组上操作(难度较大,理解困难)。在利用数组的特殊之处,找到合理的方法。