Checking if two strings are permutations of each other

前端 未结 30 938
感情败类
感情败类 2020-12-05 08:19

How to determine if two strings are permutations of each other

相关标签:
30条回答
  • 2020-12-05 09:10

    This is an O(N) solution, in which N is the length of the shorter string. It has a disadvantage, which is that only ASCII characters are acceptable. If we want better applicability, we may substitute a hash table for the int charNums[]. But it also means C wouldn't be a good choice, coz' there is no standard hash table implementation for C.

    int is_permutation(char *s1, char *s2)
    {
        if ((NULL == s1) ||
            (NULL == s2)) {
            return false;
        }
    
        int static const
        _capacity = 256;    // Assumption
        int
        charNums[_capacity] = {0};
        char
        *cRef1 = s1,
        *cRef2 = s2;
        while ('\0' != *cRef1 && '\0' != *cRef2) {
            charNums[*cRef1] += 1;
            charNums[*cRef2] -= 1;
            cRef1++;
            cRef2++;
        }
    
        if ('\0' != *cRef1 || '\0'  != *cRef2) {
            return false;
        }
    
        for (int i = 0; i < _capacity; i++) {
            if (0 != charNums[i]) {
                return false;
            }
        }
    
        return true;
    }
    
    0 讨论(0)
  • 2020-12-05 09:10

    Here is a simple program I wrote that gives the answer in O(n) for time complexity and O(1) for space complexity. It works by mapping every character to a prime number and then multiplying together all of the characters in the string's prime mappings together. If the two strings are permutations then they should have the same unique characters each with the same number of occurrences.

    Here is some sample code that accomplishes this:

    // maps keys to a corresponding unique prime
    static Map<Integer, Integer> primes = generatePrimes(255); // use 255 for
                                                                // ASCII or the
                                                                // number of
                                                                // possible
                                                                // characters
    
    public static boolean permutations(String s1, String s2) {
        // both strings must be same length
        if (s1.length() != s2.length())
            return false;
    
        // the corresponding primes for every char in both strings are multiplied together
        int s1Product = 1;
        int s2Product = 1;
    
        for (char c : s1.toCharArray())
            s1Product *= primes.get((int) c);
    
        for (char c : s2.toCharArray())
            s2Product *= primes.get((int) c);
    
        return s1Product == s2Product;
    
    }
    
    private static Map<Integer, Integer> generatePrimes(int n) {
    
        Map<Integer, Integer> primes = new HashMap<Integer, Integer>();
    
        primes.put(0, 2);
    
        for (int i = 2; primes.size() < n; i++) {
            boolean divisible = false;
    
            for (int v : primes.values()) {
                if (i % v == 0) {
                    divisible = true;
                    break;
                }
            }
    
            if (!divisible) {
                primes.put(primes.size(), i);
                System.out.println(i + " ");
            }
        }
    
        return primes;
    
    }
    
    0 讨论(0)
  • 2020-12-05 09:12

    I'm working on a Java library that should simplify your task. You can re-implement this algorithm using only two method calls:

    boolean arePermutationsOfSameString(String s1, String s2) {
        s1 = $(s1).sort().join(); 
        s2 = $(s2).sort().join();
        return s1.equals(s2);
    }
    

    testcase

    @Test
    public void stringPermutationCheck() {
        // true cases
        assertThat(arePermutationsOfSameString("abc", "acb"), is(true));
        assertThat(arePermutationsOfSameString("bac", "bca"), is(true));
        assertThat(arePermutationsOfSameString("cab", "cba"), is(true));
    
        // false cases
        assertThat(arePermutationsOfSameString("cab", "acba"), is(false));
        assertThat(arePermutationsOfSameString("cab", "acbb"), is(false));
    
        // corner cases
        assertThat(arePermutationsOfSameString("", ""), is(true));
        assertThat(arePermutationsOfSameString("", null), is(true));
        assertThat(arePermutationsOfSameString(null, ""), is(true));
        assertThat(arePermutationsOfSameString(null, null), is(true));
    }
    

    PS

    In the case you can clone the souces at bitbucket.

    0 讨论(0)
  • 2020-12-05 09:12

    Variation on other approaches but this one uses 2 int arrays to track the chars, no sorting, and you only need to do 1 for loop over the strings. The for loop I do over the int arrays to test the permutation is a constant, hence not part of N.

    Memory is constant.

    O(N) run time.

    // run time N, no sorting, assume 256 ASCII char set
    public static boolean isPermutation(String v1, String v2) {
    
        int length1 = v1.length();
        int length2 = v2.length();
        if (length1 != length2)
            return false;
    
        int s1[] = new int[256];
        int s2[] = new int[256];
    
        for (int i = 0; i < length1; ++i) {
            int charValue1 = v1.charAt(i);
            int charValue2 = v2.charAt(i);
            ++s1[charValue1];
            ++s2[charValue2];
        }
    
        for (int i = 0; i < s1.length; ++i) {
    
            if (s1[i] != s2[i])
                return false;
        }
        return true;
      }
    }
    

    Unit Tests

    @Test
    public void testIsPermutation_Not() {
        assertFalse(Question3.isPermutation("abc", "bbb"));
    }
    
    @Test
    public void testIsPermutation_Yes() {
        assertTrue(Question3.isPermutation("abc", "cba"));
        assertTrue(Question3.isPermutation("abcabcabcabc", "cbacbacbacba"));
    }
    
    0 讨论(0)
  • 2020-12-05 09:13

    Based on the comment on this solution, https://stackoverflow.com/a/31709645/697935 here's that approach, revised.

    private static boolean is_permutation(String s1, String s2) {
        HashMap<Character, Integer> map = new HashMap<Character, Integer>();
        int count = 1;
        if(s1.length()!=s2.length()) {
            return false;
        }
        for(Character c: s1.toCharArray()) {
            if(!map.containsKey(c)) {
                map.put(c, 1);
            }
            else {
                map.put(c, map.get(c) + 1);
            }
        }
        for(Character c: s2.toCharArray()) {
            if(!map.containsKey(c)) {
                return false;
            }
            else {
                map.put(c, map.get(c) - 1);
            }
        }
        for(Character c: map.keySet()) {
            if(map.get(c) != 0) { return false; }
        }
        return true;
    }
    
    0 讨论(0)
  • 2020-12-05 09:15

    Create two methods:

    1. First method takes a string and returns a sorted string:

    public String sort(String str) { char char_set[] = str.toCharArray(); Arrays.sort(char_set); return new String(char_set); }

    2. Second method takes two strings and return a boolean:

       `public boolean sort(String x, String y) {
           if (x.length() != y.length()) {
               System.out.println("false");
               return false;
           }
           System.out.println(sort(x).equals(sort(y)));
           return sort(x).equals(sort(y));
       }`
    
    0 讨论(0)
提交回复
热议问题