Most efficient method to check for range of numbers within number without duplicates

后端 未结 2 686
难免孤独
难免孤独 2020-12-11 11:34

Given a number n , a minimum number min , a maximum number max , what is the most efficient method to determine

  1. Numbe

2条回答
  •  轻奢々
    轻奢々 (楼主)
    2020-12-11 12:00

    Associative arrays approach:

    This has the advantage of being easily understandable.

    function checkDigits(min, max, n) {
        var digits = Array(10);                   // Declare the length of the array (the 10 digits) to avoid any further memory allocation
        while (n) {
            d = (n % 10);                         // Get last digit
            n = n / 10 >>0;                       // Remove it from our number (the >>0 bit is equivalent to compose(Math.floor, Math.abs))
            if (d < min || d > max || digits[d])  // Test if "d" is outside the range or if it has been checked in the "digits" array
                return false;
            else
                digits[d] = true;                 // Mark the digit as existing
        }
    }
    

    var min = 2
    , max = 7
    , arr = [81, 35, 22, 45, 49];
    
    function checkDigits(min, max, n) {
        var digits = Array(10);                   // Declare the length of the array (the 10 digits) to avoid any further memory allocation
        while (n) {
            d = (n % 10);                         // Get last digit
            n = n / 10 >>0;                       // Remove it from our number (the >>0 bit is equivalent to compose(Math.floor, Math.abs))
            if (d < min || d > max || digits[d])  // Test if "d" is outside the range or if it has been checked in the "digits" array
                return false;
            else
                digits[d] = true;                 // Mark the digit as existing
        }
        return true;
    }
    
    for (var i = 0; i < arr.length; i++) {
      console.log(checkDigits(min, max, arr[i]), i, arr[i])
    }

    Binary mask approach:

    This replaces the Array with an integer that is in effect used as an array of bits. It should be faster.

    function checkDigits(min, max, n) {
        var digits = 0;                   
        while (n) {
            d = (n % 10);                         
            n = n / 10 >>0;
            if (d < min || d > max || (digits & (1 << d)))
                return false;
            else
                digits |= 1 << d;
        }
        return true;
    }
    

    function checkDigits(min, max, n) {
        var digits = 0;                   
        while (n) {
            d = (n % 10);                         
            n = n / 10 >>0;
            if (d < min || d > max || (digits & (1 << d)))
                return false;
            else
    			digits |= 1 << d;
        }
        return true;
    }

    Explanation for binary mask approach:

    1 << d creates a bit mask, an integer with the d bit set and all other bits set to 0.
    digits |= 1 << d sets the bit marked by our bit mask on the integer digits.
    digits & (1 << d) compares the bit marked by our bit mask with digits, the collection of previously marked bits.
    See the docs on bitwise operators if you want to understand this in detail.

    So, if we were to check 626, our numbers would go like this:

    ________n_____626_______________
               |
            d  |  6
         mask  |  0001000000
       digits  |  0000000000
               |
    ________n_____62________________
               |
            d  |  2
         mask  |  0000000100
       digits  |  0001000000
               |
    ________n_____6_________________
               |
            d  |  6
         mask  |  0001000000
       digits  |  0001000100
                     ^
                   bit was already set, return false
    

提交回复
热议问题