数组中重复的数

数组中重复的数

题目描述

在一个长度为n的数组里的所有数字都在0到n-1的范围内。 数组中某些数字是重复的,但不知道有几个数字是重复的。也不知道每个数字重复几次。请找出数组中任意一个重复的数字。

例如,如果输入长度为7的数组{2,3,1,0,2,5,3},那么对应的输出是第一个重复的数字2。

思路

1、本人最初的思路
将每一个数与其后的所有数相比,如果相等则返回重复的数
时间复杂度:O(n的平方),空间复杂度:O(1)

 public boolean duplicate(int numbers[],int length,int [] duplication) {
        int i;
        int j;
        boolean flag=false;
         if(numbers==null||numbers.length<=0){
               duplication[0]=-1;
            return flag;
            
        }
        for( i=0;i<numbers.length;i++){
            if(numbers[i]<0||numbers[i]>=numbers.length){
                duplication[0]=-1;
                return flag;
            }
        }
        for(i=0;i<length;i++){
            for(j=length-1;j>i;j--){   //从最后的元素遍历
                if(numbers[j]==numbers[i]){
                    break;
                }
            }
            if(j>i){
                duplication[0]=numbers[i];
               flag= true;
                break;
            }
     }
        return flag;
    }
  public boolean duplicate(int numbers[],int length,int [] duplication) {
        int i;
        int j;
        boolean flag=false;
         if(numbers==null||numbers.length<=0){
               duplication[0]=-1;
            return flag;
            
        }
        for(i=0;i<numbers.length;i++){
            if(numbers[i]<0||numbers[i]>=numbers.length){
                duplication[0]=-1;
                return flag;
            }
        }
        for(i=0;i<length-1;i++){
            for(j=i+1;j<length;j++){  //从下一个元素开始遍历
                if(numbers[j]==numbers[i]){
                   duplication[0]=numbers[i];
                   flag= true;
                   break;
                }
            }
            if(j<length){
                 break;
            }
          
     }
        return flag;
    }

实际上效率较低,代码质量不佳

2、字符串连接
将所有的数组元素连接成一个字符串,然后遍历字符串,如果indexOf和lastIndexOf的位置不同则存在重复
时间复杂度:O(n),空间复杂度:O(1)

public boolean duplicate(int numbers[],int length,int [] duplication) {
      StringBuffer str=new StringBuffer();
        for(int i=0;i<length;i++){
            str.append(numbers[i]+"");
        }
        for(int j=0;j<length;j++){
            if(str.indexOf(numbers[j]+"")!=str.lastIndexOf(numbers[j]+"")){
                duplication[0]=numbers[j];
                return true;
            }
        }
        return false;
    }

虽然通过校验,但是仍然存在一些问题,例如序列长度为12,{0,1,2,3,4,5,6,7,8,9,10,11}
连接成的字符串为01234567891011,str.indexOf(0)==0,str.lastIndexOf(0)==11程序返回有重复,但是实际上却无重复

3、排序:
将数组排序,然后扫描数组中前后相连的元素,相同即有重复
时间复杂度为:O(n的平方),空间复杂度为:O(1)

public class Solution {
	//冒泡排序1
     public static int[] Sort(int array[]){
        int temp;
         if(array.length<=1){
            return array;
        }
         else{
         	//-从前往后冒泡
               for(int i=0;i<array.length-1;i++){
            for(int j=0;j<array.length-i-1;j++){
                if(array[j]>array[j+1]){
                    temp=array[j];
                    array[j]=array[j+1];
                    array[j+1]=temp;
                }
            }
            }
            //-从后往前冒泡
            for(int i=0;i<array.length-1;i++){
                for(int j=array.length-1;j>i;j--){
                if(array[j]<array[j-1]){
                    temp=array[j];
                    array[j]=array[j-1];
                    array[j-1]=temp;
                }//if
            }//j
        }//i
    }//else
      
        return array;
    }
    //验证函数
    public boolean duplicate(int numbers[],int length,int [] duplication) {
         boolean flag=false;
        int []array=new int[length];
        if(numbers==null||numbers.length<=0){
               duplication[0]=-1;
            return flag;
            
        }
        for(int i=0;i<numbers.length;i++){
            if(numbers[i]<0||numbers[i]>=numbers.length){
                duplication[0]=-1;
                return flag;
            }
        }
        array=Sort(numbers);
        if(array.length<=1){
               duplication[0] = -1;
        }
        else{
            for(int j=0;j<array.length-1;j++){
            if(array[j]==array[j+1]){
                duplication[0] = array[j];
                flag = true;
                break;
            }
        }
        }
        
         return flag;  
    } 
  }

4.哈希表
从头开始遍历,每遇到一个元素就花费O(1)的时间查询哈希表,查不到就插入表中,查到就返回重复的数。
时间复杂度:O(n) 空间复杂度:O(n)
1.

import java.util.Map;
import java.util.HashMap;
    public boolean duplicate(int numbers[],int length,int [] duplication) {
       if(numbers==null||numbers.length<=0){
               duplication[0]=-1;
            return false;
            
        }
        for(int i=0;i<numbers.length;i++){
            if(numbers[i]<0||numbers[i]>=numbers.length){
                duplication[0]=-1;
                  return false;
            }
        }
        HashMap<Integer,Boolean> hm=new HashMap<>();
        for(int i=0;i<length;i++){
            if(hm.containsKey(numbers[i])){
                duplication[0]=numbers[i];
                return true;
            }else{
                hm.put(numbers[i],true);//插入表中
            }
        }
        return false;
    }
}
}

import java.util.HashMap;  
import java.util.Set;      
public class Solution {

   public boolean duplicate(int numbers[], int length, int[] duplication) {
  	if(numbers==null||numbers.length<=0){
               duplication[0]=-1;
            return false;
            
        }
        for(int i=0;i<numbers.length;i++){
            if(numbers[i]<0||numbers[i]>=numbers.length){
                duplication[0]=-1;
                  return false;
            }
        }
        HashMap <Integer, Integer>map = new HashMap<Integer, Integer>();
        //hash映射
        for (int i = 0; i < length; i++) {
            if (map.containsKey(numbers[i])) {
                int temp = map.get(numbers[i]);
                map.put(numbers[i], ++temp);
            } else
                map.put(numbers[i], 1);
        }
        //找到第一个重复的 return
        Set<Integer> set = map.keySet();
        for(int i : set) {
            if (map.get(i) >= 2 ) {
                duplication[0] = i;
                return true;
            }
        }
        return false;
    }
     
  }


5.交换
0~n-1正常的排序应该是A[i]=i;因此可以通过交换的方式,将它们都各自放回属于自己的位置;

从头到尾扫描数组A,当扫描到下标为i的数字m时,首先比较这个数字m是不是等于i,

如果是,则继续扫描下一个数字;

如果不是,则判断它和A[m]是否相等,如果是,则找到了第一个重复的数字(在下标为i和m的位置都出现了m);如果不是,则把A[i]和A[m]交换,即把m放回属于它的位置;

重复上述过程,直至找到一个重复的数字;

时间复杂度:O(n),空间复杂度:O(1)—所有的操作步骤都是在输入数组上进行的,不需要额外分配空间

(将每个数字放到属于自己的位置最多交换两次)

public class Solution {

    public boolean duplicate(int numbers[],int length,int [] duplication) {
        int temp;
        boolean flag=false;
        if(numbers==null||numbers.length<=0){
               duplication[0]=-1;
            return flag;    
        }
        for(int i=0;i<numbers.length;i++){
            if(numbers[i]<0||numbers[i]>=numbers.length){
                duplication[0]=-1;
                return flag;
            }
        }
          for(int j=0;j<numbers.length;j++){
              while(numbers[j]!=j){
                  if(numbers[j]==numbers[numbers[j]]){
                     duplication[0] = numbers[j];
                     flag = true;  
                     return flag;
                  }
                   temp=numbers[j];
                   numbers[j]=numbers[temp];
                   numbers[temp]=temp;
              }
            }   
     
         return flag;  
    } 
  }

6.Set O(n),O(n)

 public int findDuplicate(int[] nums) {
        Set<Integer> seen = new HashSet<Integer>();
        for (int num : nums) {
            if (seen.contains(num)) {
                return num;
            }
            seen.add(num);
        }

        return -1;
    }

题目2----不修改数组

环检测算法(Floyd’s Tortoise and Hare)

  • 分析:当兔子和乌龟在环形跑道上跑步时,在某一时刻,兔子会追上乌龟

  • 两个步骤,第一个步骤是确定链表是否有环(也就是重复的数字),第二个步骤是确定环的入口点(重复的数字)在哪里。

    1.首先,我们初始化两个指针,一个快速的 hare 指针,一个慢的Tortoise 指针。让hare 一次走两个节点,Tortoise 一个节点。最终,Tortoise 和hare 总会在相同的节点相遇,这样就可以证明是否有环。
    2.我们初始化两个指针:ptr1指向列表头部的指针,指向ptr2交叉点的指针 。然后,我们把他们每个每次前进1个节点,直到他们相遇; 他们相遇的节点是环的入口,我们就可以得出结果。

  • 时间复杂度O(n)空间复杂度O(1)

 public int findDuplicate(int[] nums) {
        // Find the intersection point of the two runners.
        int tortoise = nums[0];
        int hare = nums[0];
        do {
            tortoise = nums[tortoise];
            hare = nums[nums[hare]];
        } while (tortoise != hare);

        // Find the "entrance" to the cycle.
        int ptr1 = nums[0];
        int ptr2 = tortoise;
        while (ptr1 != ptr2) {
            ptr1 = nums[ptr1];
            ptr2 = nums[ptr2];
        }
        return ptr1;
    }

猜你喜欢

转载自blog.csdn.net/u013244775/article/details/84847414