Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Checking whether two numbers are permutation of each other?

Tags:

c++

performance

c

Given two numbers a, b such that 1 <= a , b <= 10000000000 (10^10). My problem is to check whether the digits in them are permutation of each other or not. What is the fastest way of doing it? I was thinks of using hashing but unable to find any suitable hash function. Any suggestions?

For e.g - 123 is a valid permutation of 312

Also I don't want to sort the digits in the numbers.

like image 910
Ravi Gupta Avatar asked Jul 10 '10 11:07

Ravi Gupta


3 Answers

a and b are anagrams if they have the same number of each digit. So basically the fastest way seems to be, counting the digits for a and b:

int c[10]={0,0,0,0,0,0,0,0,0,0}

while (a) { c[a%10]++; a/=10; }
while (b) { c[b%10]--; b/=10; }

int res=1;
for (int i=0;i<10;i++) res &= c[i]==0;
printf(res?"yes":"no");
like image 108
Nordic Mainframe Avatar answered Sep 20 '22 09:09

Nordic Mainframe


If you mean the characters of the numbers (such as 1927 and 9721), there are (at least) a couple of approaches.

If you were allowed to sort, one approach is to simply sprintf them to two buffers, sort the characters in the buffers, then see if the strings are equal.

However, given your desire to not sort the digits, another alternative is to set up a ten-element array, with all elements initially set to zero, then process each digit in the first number, incrementing the relevant element.

Then do the same with the second number but decrementing.

If, at the end, it's still all zeros, the numbers were a permutation of each other.

This is efficient in that it's an O(n) algorithm where n is the number of digits in the two numbers. The pseudo-code for such a beast would be something like:

def arePermutations (num1, num2):
    create array count, ten elements, all zero.
    for each digit in num1:
        increment count[digit]
    for each digit in num2:
        decrement count[digit]
    for each item in count:
        if item is non-zero:
            return false
    return true

In C, the following complete program illustrates how this can be done:

#include <stdio.h>
#include <stdlib.h>

#define FALSE (1==0)
#define TRUE  (1==1)

int hasSameDigits (long num1, long num2) {
    int digits[10];
    int i;

    for (i = 0; i < 10; i++)      // Init all counts to zero.
        digits[i] = 0;

    while (num1 != 0) {           // Process all digits.
        digits[num1%10]++;        // Increment for least significant digit.
        num1 /= 10;               // Get next digit in sequence.
    }

    while (num2 != 0) {           // Same for num2 except decrement.
        digits[num2%10]--;
        num2 /= 10;
    }

    for (i = 0; i < 10; i++)
        if (digits[i] != 0)       // Any count different, not a permutation.
            return FALSE;

    return TRUE;                  // All count identical, was a permutation.
}

 

int main (int c, char *v[]) {
    long v1, v2;

    if (c != 3) {
        printf ("Usage: %s <number1> <number2>\n", v[0]);
        return 1;
    }

    v1 = atol (v[1]);
    v2 = atol (v[2]);
    if (hasSameDigits (v1, v2)) {
        printf ("%d and %d are permutations\n", v1, v2);
    } else {
        printf ("%d and %d are not permutations\n", v1, v2);
    }

    return 0;
}

Simply pass it two (positive) numbers and, assuming they fit in a long, it'll tell you whether they have the same digit counts.

like image 40
paxdiablo Avatar answered Sep 19 '22 09:09

paxdiablo


Is it homework?

Calculate number of appearances of each digit and compare them, if they are same then one number can be converted to other using permutation.

like image 39
Artyom Avatar answered Sep 20 '22 09:09

Artyom