How to compare two arrays of integers order-insensitively

前端 未结 8 1080
梦谈多话
梦谈多话 2021-01-19 13:23

I want Java code that can compare in this way (for example):

<1 2 3 4>  = <3 1 2 4>
<1 2 3 4> != <3 4 1 1>

I can\'t

相关标签:
8条回答
  • 2021-01-19 13:35

    Here is a fix for the code that you posted.

    for(int i = 0; i < n; i++)
    {
        int j;
        for(j = 0; j < n; j++)
        {   
            if(a[i] == b[j]) break;
        }
        if (j == n) return false;
    }
    return true;
    

    That algorithm is going to break done for arrays that contain duplicates, however. For example, the array {1, 1, 2, 3} will be found as a match to the array {1, 2, 2, 3}.

    I would highly recommend that you implement a sort-and-compare algorithm instead.

    0 讨论(0)
  • 2021-01-19 13:37

    This is a O(n^2) problem. No other solution is faster than comparing the two arrays directly.

    The Virgil's solution is cool, except for the fact that it is not really O(n) performance. It is really O(n+1000) performance. The array comparison second time to set the boolean variable is costly and backfires in small arrays.

    The solution you wrote is the best except for a bugs.

    Here is the error corrected version.

    boolean[] matchedPositions = new boolean[n];
    for(int k = 0; k < n; k++
    {
        matchedPositions[k] = false;
    }
    
    for(int i = 0; i < n; i++)
    {
        for(int j = 0; j < n; j++)
        {   
            if(matchedPositions[j] == false && a[i] == a[j])
            {
                 matchedPositions[j] = true;
                 break;
            }
    
            if(j == n - 1)
            {
                return false;
            }
        }
    }
    return true;
    

    In this case if in case the integer matches then the inner loop will break and set or flag the matched position. This is required for arrays with duplicate entries, this will avoid two entries in left array matching with one entry in the right array.

    If in case the match did not happen, which is identified by j == n - 1, you will return false.

    Since we are expecting a default value of false in boolean its better to flag initialize it.

    In reality, this solution has O(n log n + n) performance penalty. Sort and compare has a performance penalty of O(n^2 + n) too. Sort has O(n^2) performance and one loop for checking. But sorting changes the contents of the array and this does not.

    0 讨论(0)
  • 2021-01-19 13:42

    Sort & compare. You can't get the complexity better than that, and any "improvement" that you do on the speed comes at the risk that your code will be wrong.

    [edit] Actually.... if you know your numbers are relatively small (e.g. say: the arrays only contain numbers between 0 and 1000), that there's an alternative in O(n). Something like this (sorry if the syntax is wrong, I didn't use java lately):

    int count[1001]; // already intialized to 0
    
    for(int i=0;i<n;i++){ count[a[i]]++; count[b[i]]--;}
    bool arrays_identical = true;
    for(int i=0;i<=1000 && arrays_identical; i++)
        arrays_identical &= count[i]==0;
    

    Disclaimer: this code doesn't contain "sanity checks" (i.e. the arrays are really of length "n", the numbers are in the prescribed interval) - it's only to illustrate the principle.

    0 讨论(0)
  • 2021-01-19 13:47
    Arrays.sort(a);
    Arrays.sort(b);
    return Arrays.equals(a, b);
    
    0 讨论(0)
  • 2021-01-19 13:49

    Before you actually start a more computationally complex solution, you can run a fast O(n) test to see if the arrays are the same. There are times when this this will result in a false positive, and you can use more computationally intensive means to investigate further. If it returns false, you can be assured that the arrays are different.

    The basic approach is to do a cummulative XOR between the ith elements of the two arrays. If the resulting XOR is non-zero then you know that the two arrays are different. If the XOR is zero, they might be the same, but more work is needed to confirm.

    int c_xor = 0;  // XOR accumulator
    
    for (int i = 0; i < n; ++i)
        c_xor ^= arr1[i] ^ arr2[i];
    
    // They're different if c_xor != 0; the might be the same if c_xor == 0
    return c_xor == 0;
    0 讨论(0)
  • 2021-01-19 13:54

    Since this is homework, I'm going to guess that a simple quadratic solution (which your original attempt is), is fine. In that case, you can do something like this:

    int count(int[] nums, int x) {
        int count = 0;
        for (int num : nums) {
            if (num == x) count++;
        }
        return count;
    }   
    boolean equals(int[] arr1, int[] arr2) {
        if (arr1.length != arr2.length) return false;
        for (int x : arr1) {
            if (count(arr1, x) != count(arr2, x)) return false;
        }
        return true;
    }
    

    This sacrifices speed for clarity: it's obviously correct!!

    Tips

    • Use for-each whenever applicable; it always read to better readability
    • Helper functions improve both readability and reusability!
    0 讨论(0)
提交回复
热议问题