Search code examples
algorithmtime-complexitypermutationproofspace-complexity

Proof: Check if two integer arrays are permutations of each other using linear time and constant space


I was interested in creating a simple array problem with running time and space constraints. It seems that I have found a solution to my problem. Please read the initial description comment of the problem in the following java code:

 /*
 * Problem: Given two integer arrays, a and b, return whether array a is a permutation of array b.
 * Running time complexity: O(n)
 * Space complexity: O(1)
 * Example 1:
 * a = [1, 2, -3]
 * b = [2, 3, 1]
 * false
 * Example 2:
 * a = [1, 2, 3]
 * b = [0, 1]
 * false
 * Example 3:
 * a = [2, 7, 3, 5]
 * b = [5, 7, 2, 3]
 * true
 * Example 4:
 * a = [1, -2, 10000]
 * b = [10000, 1, -2]
 * true
 * Example 5:
 * a = [1, 2, 2, 3]
 * b = [3, 2, 1, 3]
 * false
 * Example 6:
 * a = [2, 2, 4, 4]
 * b = [3, 3, 3, 3]
 * false
 * Example 7:
 * a = [4, 4, 2, 2, 4, 4]
 * b = [4, 3, 3, 3, 3, 4]
 * false
 * ----------------------
 * Input is two space separated lines of integers
 * Output is true or false
 * Terminal Example:
 * 1 4 9 25
 * 4 25 9 2
 * false
 * ----------------------
 * Solution:
 * 1. Average displacement (delta) between the elements of array a and array b equals 0
 * AND
 * 2. xor-ing all of the values between the elements of array a and array b equals 0
 * AND
 * 3. mins are the same and maxs are the same
 * @author (David Brewster)
 * @version (27.01.2016) (requires java 1.8)
 */

import java.util.Scanner;
import java.util.Arrays;
public class ArrayProb
{
    public static int xorComparison(int[] a, int[] b, int i, int xortotal)
    {
        return i == a.length ?
                xortotal : xorComparison(a, b, i + 1, xortotal ^ a[i] ^ b[i]);
    }
    public static int deltaComparison(int[] a, int[] b, int i, int deltatotal)
    {
        return i == a.length ?
                deltatotal : deltaComparison(a, b, i + 1, deltatotal + a[i] - b[i]);
    }
    public static int minComparison(int[] a, int[] b, int i, int amin, int bmin)
    {
        return i == a.length ?
                amin-bmin : minComparison(a, b, i + 1,
                a[i] < amin ? a[i] : amin,
                b[i] < bmin ? b[i] : bmin);
    }
    public static int maxComparison(int[] a, int[] b, int i, int amax, int bmax)
    {
        return i == a.length ?
                amax-bmax : maxComparison(a, b, i+1,
                a[i] > amax ? a[i] : amax,
                b[i] > bmax ? b[i] : bmax);
    }
    public static boolean arePermutations(int[] a, int[] b)
    {
        if (a.length == b.length)
        {
            boolean d = xorComparison(a, b, 0, 0) == 0;
            boolean e = deltaComparison(a, b, 0, 0) == 0;
            boolean f = maxComparison(a, b, 0, Integer.MIN_VALUE, Integer.MIN_VALUE) == 0;
            boolean g = minComparison(a, b, 0, Integer.MAX_VALUE, Integer.MAX_VALUE) == 0;
            return d && e && f && g;
        }
        else
        {
            return false;
        }
    }
    public static void main(String[] args)
    {
        Scanner input = new Scanner(System.in);
        int[] a = Arrays.stream(input.nextLine().split(" ")).mapToInt(Integer::parseInt).toArray();
        int[] b = Arrays.stream(input.nextLine().split(" ")).mapToInt(Integer::parseInt).toArray();
        System.out.println(arePermutations(a, b));
    }
}

Even thought the algorithm seems to work for most cases (at least all that I have tested so far), how would I go about proving that the solution is correct 100% of the time?


Solution

  • What you are basically trying to do is computing a fixed size fingerprint of each array (representing a multiset) and then determining equality of the multisets by comparing the fingerprints.

    This is clearly not possible because there is an infinite number of multisets but if space is constant, there is only a limited number of fingerprints. So you will inevitably find examples where two different multisets map to the same fingerprint.