Checking if two strings are permutations of each other in Python

前端 未结 22 2297
旧时难觅i
旧时难觅i 2020-12-08 16:04

I\'m checking if two strings a and b are permutations of each other, and I\'m wondering what the ideal way to do this is in Python. From the Zen of

相关标签:
22条回答
  • 2020-12-08 16:14

    Here's martinus code in python. It only works for ascii strings:

    def is_permutation(a, b):
        if len(a) != len(b):
            return False
    
        char_count = [0] * 256
        for c in a:
            char_count[ord(c)] += 1
    
        for c in b:
            char_count[ord(c)] -= 1
            if char_count[ord(c)] < 0:
                return False
    
        return True
    
    0 讨论(0)
  • 2020-12-08 16:16

    First, for solving such problems, e.g. whether String 1 and String 2 are exactly the same or not, easily, you can use an "if" since it is O(1). Second, it is important to consider that whether they are only numerical values or they can be also words in the string. If the latter one is true (words and numerical values are in the string at the same time), your first solution will not work. You can enhance it by using "ord()" function to make it ASCII numerical value. However, in the end, you are using sort; therefore, in the worst case your time complexity will be O(NlogN). This time complexity is not bad. But, you can do better. You can make it O(N). My "suggestion" is using Array(list) and set at the same time. Note that finding a value in Array needs iteration so it's time complexity is O(N), but searching a value in set (which I guess it is implemented with HashTable in Python, I'm not sure) has O(1) time complexity:

    def Permutation2(Str1, Str2):
    
    ArrStr1 = list(Str1) #convert Str1 to array
    SetStr2 = set(Str2) #convert Str2 to set
    
    ArrExtra = []
    
    if len(Str1) != len(Str2): #check their length
        return False
    
    elif Str1 == Str2: #check their values
        return True
    
    for x in xrange(len(ArrStr1)):
        ArrExtra.append(ArrStr1[x])
    
    for x in xrange(len(ArrExtra)): #of course len(ArrExtra) == len(ArrStr1) ==len(ArrStr2)
        if ArrExtra[x] in SetStr2: #checking in set is O(1)
            continue
        else:
            return False
    
    return True
    
    0 讨论(0)
  • 2020-12-08 16:17

    Checking if two strings are permutations of each other in Python

    # First method
    def permutation(s1,s2):
     if len(s1) != len(s2):return False;
     return ' '.join(sorted(s1)) == ' '.join(sorted(s2))
    
    
    # second method
    def permutation1(s1,s2):
     if len(s1) != len(s2):return False;
     array = [0]*128;
     for c in s1:
     array[ord(c)] +=1
     for c in s2:
       array[ord(c)] -=1
       if (array[ord(c)]) < 0:
         return False
     return True
    
    0 讨论(0)
  • 2020-12-08 16:18

    Sorry that my code is not in Python, I have never used it, but I am sure this can be easily translated into python. I believe this is faster than all the other examples already posted. It is also O(n), but stops as soon as possible:

    public boolean isPermutation(String a, String b) {
        if (a.length() != b.length()) {
            return false;
        }
    
        int[] charCount = new int[256];
        for (int i = 0; i < a.length(); ++i) {
            ++charCount[a.charAt(i)];
        }
    
        for (int i = 0; i < b.length(); ++i) {
            if (--charCount[b.charAt(i)] < 0) {
                return false;
            }
        }
        return true;
    }
    

    First I don't use a dictionary but an array of size 256 for all the characters. Accessing the index should be much faster. Then when the second string is iterated, I immediately return false when the count gets below 0. When the second loop has finished, you can be sure that the strings are a permutation, because the strings have equal length and no character was used more often in b compared to a.

    0 讨论(0)
  • 2020-12-08 16:18

    I did a pretty thorough comparison in Java with all words in a book I had. The counting method beats the sorting method in every way. The results:

    Testing against 9227 words.
    
    Permutation testing by sorting ... done.        18.582 s
    Permutation testing by counting ... done.       14.949 s
    

    If anyone wants the algorithm and test data set, comment away.

    0 讨论(0)
  • 2020-12-08 16:20

    Here are some timed executions on very small strings, using two different methods:
    1. sorting
    2. counting (specifically the original method by @namin).

    a, b, c = 'confused', 'unfocused', 'foncused'
    
    sort_method = lambda x,y: sorted(x) == sorted(y)
    
    def count_method(a, b):
        d = {}
        for x in a:
            d[x] = d.get(x, 0) + 1
        for x in b:
            d[x] = d.get(x, 0) - 1
        for v in d.itervalues():
            if v != 0:
                return False
        return True
    

    Average run times of the 2 methods over 100,000 loops are:

    non-match (string a and b)

    $ python -m timeit -s 'import temp' 'temp.sort_method(temp.a, temp.b)'
    100000 loops, best of 3: 9.72 usec per loop
    $ python -m timeit -s 'import temp' 'temp.count_method(temp.a, temp.b)'
    10000 loops, best of 3: 28.1 usec per loop
    

    match (string a and c)

    $ python -m timeit -s 'import temp' 'temp.sort_method(temp.a, temp.c)'
    100000 loops, best of 3: 9.47 usec per loop
    $ python -m timeit -s 'import temp' 'temp.count_method(temp.a, temp.c)'
    100000 loops, best of 3: 24.6 usec per loop
    

    Keep in mind that the strings used are very small. The time complexity of the methods are different, so you'll see different results with very large strings. Choose according to your data, you may even use a combination of the two.

    0 讨论(0)
提交回复
热议问题