面试题3 判断一个String是否是另一个String的排列组合

题目要求是 给定2个 String s1 和 s2, 判断 s1 是否是和 s2 只是字母排列顺序不同

比如 dog 和 odg, 他们只是字母排列顺序不同 那么方法应该返回 true 

相反 如果是 dog 和 dag, 会返回 false

另外 如果是 dog 和 ddog 也应返回 false

解题思路是先将两个 String 按字母顺序排序 排序之后 如果其中一个 String 只是另一个 String 的不同顺序版 那么排序之后两个 String 应该完全相同

java 代码如下

  public boolean myIsPermutation(String str1, String str2){
    char[] a1 = str1.toCharArray();
    char[] a2 = str2.toCharArray();
    sortCharArray(a1);
    sortCharArray(a2);
    return isSameCharArray(a1, a2);
  }

其中 方法 sortCharArray 使用的是随机快速排序 这里正好顺便练习一下快速排序的实现 代码如下

  public void sortCharArray(char[] a){
    sortCharArray(a, 0, a.length-1);
  }


  //sort the char array according to its ascii value by randomized quick sort algorithm
  private void sortCharArray(char[] a, int s, int e){
    if(e<=s) return;
    if(s<0 || e>=a.length) return;

    Random random = new Random();
    int n = e - s + 1;
    int pivot = random.nextInt(n) + s;
    char pivotVal = a[pivot];

    int i = s, j = e;
    while(i<j){
      if(a[i]<pivotVal){
        i++;
        continue;
      }
      if(a[j]>pivotVal){
        j--;
        continue;
      }
      if(a[i]==pivotVal && a[j]==pivotVal){
        i++;
        if(i!=j)  swap(a, i, j);
        continue;
      }
      if(i!=j)  swap(a, i, j);
    }

    sortCharArray(a, s, i-1);
    sortCharArray(a, i+1, e);
  }

 

方法 swap(int[] a, int x, int y) 的作用是 将 a[x] 和 a[y] 位置互换 代码如下 

  private void swap(char[] a, int x, int y){
    char c = a[x];
    a[x] = a[y];
    a[y] = c;
  }

 

方法 isSameCharArray 判断2个 char[] 是否在相同位置含有相同的元素 代码如下

  private boolean isSameCharArray(char[] a, char[] b){
    if(a.length != b.length) return false;
    if(a.length==0 && b.length==0) return true;

    for(int i=0; i<a.length; i++) if(a[i]!=b[i])  return false;

    return true;
  }

上述方法中 排序需要 O(logn)的时间  其他操作都是O(n) 所以总时间复杂度是O(logn) 

因为2个 char 数组需要 O(n) 的空间 快速排序是原址的 不需要额外空间 所以空间复杂度是 O(n)

 

还有另一种更好的解法

思路是判断2个 String 是否含有相同的字母 每个不同字母的数量是否相同 如果相同则 true 否则  则 false

代码如下

  public boolean isPermutation(String s, String t){
    if(s.length()!=t.length())  return false;
    int[] letters = new int[256];

    char[] s_array = s.toCharArray();

    for(char c:s_array) letters[c]++;

    for(int i=0; i<t.length(); i++){
      int c = (int)t.charAt(i);
      if(--letters[c]<0)  return false;
    }
    return true;
  }

上述方法中 无需排序两个 String 所以时间复杂度提高到了 O(n) 空间复杂度上 由于还是需要复制 String 到 char[] 所以依然是 O(n) 

此方法是目前最优解

posted @ 2015-12-19 04:33  橙喵moe  阅读(703)  评论(0)    收藏  举报