Algorithm to determine if array contains n…n+m?

前端 未结 30 3094
清酒与你
清酒与你 2020-11-28 01:45

I saw this question on Reddit, and there were no positive solutions presented, and I thought it would be a perfect question to ask here. This was in a thread about interview

30条回答
  •  轻奢々
    轻奢々 (楼主)
    2020-11-28 02:08

    MY CURRENT BEST OPTION

    def uniqueSet( array )
      check_index = 0; 
      check_value = 0; 
      min = array[0];
      array.each_with_index{ |value,index|
             check_index = check_index ^ ( 1 << index );
             check_value = check_value ^ ( 1 << value );
             min = value if value < min
      } 
      check_index =  check_index  << min;
      return check_index == check_value; 
    end
    

    O(n) and Space O(1)

    I wrote a script to brute force combinations that could fail that and it didn't find any. If you have an array which contravenes this function do tell. :)


    @J.F. Sebastian

    Its not a true hashing algorithm. Technically, its a highly efficient packed boolean array of "seen" values.

    ci = 0, cv = 0
    [5,4,3]{ 
      i = 0 
      v = 5 
      1 << 0 == 000001
      1 << 5 == 100000
      0 ^ 000001  = 000001
      0 ^ 100000  = 100000
    
      i = 1
      v = 4 
      1 << 1 == 000010
      1 << 4 == 010000
      000001 ^ 000010  = 000011
      100000 ^ 010000  = 110000 
    
      i = 2
      v = 3 
      1 << 2 == 000100
      1 << 3 == 001000
      000011 ^ 000100  = 000111
      110000 ^ 001000  = 111000 
    }
    min = 3 
    000111 << 3 == 111000
    111000 === 111000
    

    The point of this being mostly that in order to "fake" most the problem cases one uses duplicates to do so. In this system, XOR penalises you for using the same value twice and assumes you instead did it 0 times.

    The caveats here being of course:

    1. both input array length and maximum array value is limited by the maximum value for $x in ( 1 << $x > 0 )
    2. ultimate effectiveness depends on how your underlying system implements the abilities to:

      1. shift 1 bit n places right.
      2. xor 2 registers. ( where 'registers' may, depending on implementation, span several registers )

      edit Noted, above statements seem confusing. Assuming a perfect machine, where an "integer" is a register with Infinite precision, which can still perform a ^ b in O(1) time.

    But failing these assumptions, one has to start asking the algorithmic complexity of simple math.

    • How complex is 1 == 1 ?, surely that should be O(1) every time right?.
    • What about 2^32 == 2^32 .
    • O(1)? 2^33 == 2^33? Now you've got a question of register size and the underlying implementation.
    • Fortunately XOR and == can be done in parallel, so if one assumes infinite precision and a machine designed to cope with infinite precision, it is safe to assume XOR and == take constant time regardless of their value ( because its infinite width, it will have infinite 0 padding. Obviously this doesn't exist. But also, changing 000000 to 000100 is not increasing memory usage.
    • Yet on some machines , ( 1 << 32 ) << 1 will consume more memory, but how much is uncertain.

提交回复
热议问题