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

前端 未结 30 2970
清酒与你
清酒与你 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 01:51

    The Answer from "nickf" dows not work if the array is unsorted var_dump(testArray(array(5, 3, 1, 2, 4), 1, 5)); //gives "duplicates" !!!!

    Also your formula to compute sum([n...n+m-1]) looks incorrect.... the correct formula is (m(m+1)/2 - n(n-1)/2)

    0 讨论(0)
  • 2020-11-28 01:51

    Oops! I got caught up in a duplicate question and did not see the already identical solutions here. And I thought I'd finally done something original! Here is a historical archive of when I was slightly more pleased:


    Well, I have no certainty if this algorithm satisfies all conditions. In fact, I haven't even validated that it works beyond a couple test cases I have tried. Even if my algorithm does have problems, hopefully my approach sparks some solutions.

    This algorithm, to my knowledge, works in constant memory and scans the array three times. Perhaps an added bonus is that it works for the full range of integers, if that wasn't part of the original problem.

    I am not much of a pseudo-code person, and I really think the code might simply make more sense than words. Here is an implementation I wrote in PHP. Take heed of the comments.

    function is_permutation($ints) {
    
      /* Gather some meta-data. These scans can
         be done simultaneously */
      $lowest = min($ints);
      $length = count($ints);
    
      $max_index = $length - 1;
    
      $sort_run_count = 0;
    
      /* I do not have any proof that running this sort twice
         will always completely sort the array (of course only
         intentionally happening if the array is a permutation) */
    
      while ($sort_run_count < 2) {
    
        for ($i = 0; $i < $length; ++$i) {
    
          $dest_index = $ints[$i] - $lowest;
    
          if ($i == $dest_index) {
            continue;
          }
    
          if ($dest_index > $max_index) {
            return false;
          }
    
          if ($ints[$i] == $ints[$dest_index]) {
            return false;
          }
    
          $temp = $ints[$dest_index];
          $ints[$dest_index] = $ints[$i];
          $ints[$i] = $temp;
    
        }
    
        ++$sort_run_count;
    
      }
    
      return true;
    
    }
    
    0 讨论(0)
  • 2020-11-28 01:53

    Why do the other solutions use a summation of every value? I think this is risky, because when you add together O(n) items into one number, you're technically using more than O(1) space.

    Simpler method:

    Step 1, figure out if there are any duplicates. I'm not sure if this is possible in O(1) space. Anyway, return false if there are duplicates.

    Step 2, iterate through the list, keep track of the lowest and highest items.

    Step 3, Does (highest - lowest) equal m ? If so, return true.

    0 讨论(0)
  • 2020-11-28 01:54

    An array contains N numbers, and you want to determine whether two of the numbers sum to a given number K. For instance, if the input is 8,4, 1,6 and K is 10, the answer is yes (4 and 6). A number may be used twice. Do the following. a. Give an O(N2) algorithm to solve this problem. b. Give an O(N log N) algorithm to solve this problem. (Hint: Sort the items first. After doing so, you can solve the problem in linear time.) c. Code both solutions and compare the running times of your algorithms. 4.

    0 讨论(0)
  • 2020-11-28 01:55

    By working with a[i] % a.length instead of a[i] you reduce the problem to needing to determine that you've got the numbers 0 to a.length - 1.

    We take this observation for granted and try to check if the array contains [0,m).

    Find the first node that's not in its correct position, e.g.

    0 1 2 3 7 5 6 8 4 ;     the original dataset (after the renaming we discussed)
            ^
            `---this is position 4 and the 7 shouldn't be here
    

    Swap that number into where it should be. i.e. swap the 7 with the 8:

    0 1 2 3 8 5 6 7 4 ; 
            |     `--------- 7 is in the right place.
            `--------------- this is now the 'current' position
    

    Now we repeat this. Looking again at our current position we ask:

    "is this the correct number for here?"

    • If not, we swap it into its correct place.
    • If it is in the right place, we move right and do this again.

    Following this rule again, we get:

    0 1 2 3 4 5 6 7 8 ;     4 and 8 were just swapped
    

    This will gradually build up the list correctly from left to right, and each number will be moved at most once, and hence this is O(n).

    If there are dupes, we'll notice it as soon is there is an attempt to swap a number backwards in the list.

    0 讨论(0)
  • 2020-11-28 01:55

    Here's a working solution in O(n)

    This is using the pseudocode suggested by Hazzen plus some of my own ideas. It works for negative numbers as well and doesn't require any sum-of-the-squares stuff.

    function testArray($nums, $n, $m) {
        // check the sum. PHP offers this array_sum() method, but it's
        // trivial to write your own. O(n) here.
        if (array_sum($nums) != ($m * ($m + 2 * $n - 1) / 2)) {
            return false;    // checksum failed.
        }
        for ($i = 0; $i < $m; ++$i) {
            // check if the number is in the proper range
            if ($nums[$i] < $n || $nums[$i] >= $n + $m) {
                return false;  // value out of range.
            }
    
            while (($shouldBe = $nums[$i] - $n) != $i) {
                if ($nums[$shouldBe] == $nums[$i]) {
                    return false;    // duplicate
                }
                $temp = $nums[$i];
                $nums[$i] = $nums[$shouldBe];
                $nums[$shouldBe] = $temp;
            }
        }
        return true;    // huzzah!
    }
    
    var_dump(testArray(array(1, 2, 3, 4, 5), 1, 5));  // true
    var_dump(testArray(array(5, 4, 3, 2, 1), 1, 5));  // true
    var_dump(testArray(array(6, 4, 3, 2, 0), 1, 5));  // false - out of range
    var_dump(testArray(array(5, 5, 3, 2, 1), 1, 5));  // false - checksum fail
    var_dump(testArray(array(5, 4, 3, 2, 5), 1, 5));  // false - dupe
    var_dump(testArray(array(-2, -1, 0, 1, 2), -2, 5)); // true
    
    0 讨论(0)
提交回复
热议问题