The sword refers to the repeated numbers in the offer(50) array

Topic description

All numbers in an array of length n are in the range 0 to n-1. Some numbers in the array are repeated, but I don't know how many numbers are repeated. Also don't know how many times each number is repeated. Find any repeated number in the array. For example, if the input array {2,3,1,0,2,5,3} of length 7, then the corresponding output is the first repeated number 2.

 

Topic Analysis and Code

The title is relatively simple, but I want to write about my algorithm improvement process.

The first time I saw it, I planned to use an additional array or hash to record the number of times, and then judge that the number of times greater than 1 is repeated, like this.

function duplicate(numbers, duplication)
{
    // write code here 
    // Pay special attention here ~ find any repeated value and assign it to duplication[0] 
    // The function returns True/False 
    let map={},flag= false ;
     for (let i=0;i <numbers.length;i++ ){
         if (! map[numbers[i]]){
            map[numbers[i]]=1;
        }else{
            map[numbers[i]]++;
        }
    }
    for(let i in map){
        if(map[i]>1){
            flag=true;
            duplication[0]=i;
            break;
        }
    }
    return flag;
}

Later, I felt that the second loop was obviously multiple times. I only need to know that the number of occurrences is greater than 1, and I don't need to know the number of occurrences of all numbers, so there are

function duplicate(numbers, duplication)
{
    let map={},flag=false;
    for(let i=0;i<numbers.length;i++){
        if(!map[numbers[i]]){
            map[numbers[i]]=1;
        }else{
            duplication[0]=numbers[i];
            flag=true;
            break;
        }
    }
    return flag;
}

But it's not right, the condition of the title is not used: all numbers in an array of length n are in the range of 0 to n-1

It shows that the algorithm can also be improved.

Since all numbers in the array are from 0 to n-1, the values ​​are also in the subscript range of the array.

We can do this, in layman's terms, by placing each value in the array at the corresponding subscript position. (Numbers belong to their marks)

  1. Treat the current sequence as an array with the same subscript and the corresponding value of the subscript;
  2. Traverse the array to determine whether the value of the current bit and the subscript are equal: 2.1. If they are equal, traverse the next bit; 2.2. If they are not equal, compare the element at the current position i with the element at the position a[i]: If they are equal, success, that is, a duplicate value was found! If they are not equal, swap them. After the replacement, the value at the a[i] position corresponds to its subscript, but the element at the i position does not necessarily correspond to the subscript; repeat the operation of 2.2 until the value of the current position i is also i. i move back one place and repeat 2.

This is also the practice on the sword, this does not require additional space, and the time complexity is O(n)

function duplicate(numbers, duplication)
{
    for(let i=0;i<numbers.length;i++){
        while(i!=numbers[i]){
            if(numbers[i]==numbers[numbers[i]]){
                duplication[0]=numbers[i];
                return true;
            }
            [numbers[i],numbers[numbers[i]]]=[numbers[numbers[i]],numbers[i]];//交换
        }
    }
    return false;
}

By the way, after sorting, you can compare whether the numbers before and after are the same, but the time complexity of this method is not good, so it is discarded.

In addition, there is a way to do it on Niu Ke:

In the title, the range of numbers in the array is guaranteed to be between 0 and n-1, so you can use the existing array to set the flag. When a number is accessed, you can set the number + n on the corresponding bit, and then encounter the same When the number is , it will be found that the number on the corresponding bit is greater than or equal to n, then the number can be returned directly.

function duplicate(numbers, duplication)
{
    for(let i=0;i<numbers.length;i++){
        let index=numbers[i];
        if(index>=numbers.length){
            index-=numbers.length
        }
        if(numbers[index]>=numbers.length){
            duplication[0]=index;
            return true;
        }
        numbers[index]=numbers[index]+numbers.length;
    }
    return false;
}

 

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=324525517&siteId=291194637