找出弦的所有排列的优雅方法是什么。例如,ba的排列,将是ba和ab,但更长的字符串,如abcdefgh?是否有Java实现示例?


当前回答

倒计时Quickperm算法的通用实现,表示#1(可伸缩,非递归)。

/**
 * Generate permutations based on the
 * Countdown <a href="http://quickperm.org/">Quickperm algorithm</>.
 */
public static <T> List<List<T>> generatePermutations(List<T> list) {
    List<T> in = new ArrayList<>(list);
    List<List<T>> out = new ArrayList<>(factorial(list.size()));

    int n = list.size();
    int[] p = new int[n +1];
    for (int i = 0; i < p.length; i ++) {
        p[i] = i;
    }
    int i = 0;
    while (i < n) {
        p[i]--;
        int j = 0;
        if (i % 2 != 0) { // odd?
            j = p[i];
        }
        // swap
        T iTmp = in.get(i);
        in.set(i, in.get(j));
        in.set(j, iTmp);

        i = 1;
        while (p[i] == 0){
            p[i] = i;
            i++;
        }
        out.add(new ArrayList<>(in));
    }
    return out;
}

private static int factorial(int num) {
    int count = num;
    while (num != 1) {
        count *= --num;
    }
    return count;
}

它需要list,因为泛型不能很好地使用数组。

其他回答

/*
     * eg: abc =>{a,bc},{b,ac},{c,ab}
     * =>{ca,b},{cb,a}
     * =>cba,cab
     * =>{ba,c},{bc,a}
     * =>bca,bac
     * =>{ab,c},{ac,b}
     * =>acb,abc
     */
    public void nonRecpermute(String prefix, String word)
    {
        String[] currentstr ={prefix,word};
        Stack<String[]> stack = new Stack<String[]>();
        stack.add(currentstr);
        while(!stack.isEmpty())
        {
            currentstr = stack.pop();
            String currentPrefix = currentstr[0];
            String currentWord = currentstr[1];
            if(currentWord.equals(""))
            {
                System.out.println("Word ="+currentPrefix);
            }
            for(int i=0;i<currentWord.length();i++)
            {
                String[] newstr = new String[2];
                newstr[0]=currentPrefix + String.valueOf(currentWord.charAt(i));
                newstr[1] = currentWord.substring(0, i);
                if(i<currentWord.length()-1)
                {
                    newstr[1] = newstr[1]+currentWord.substring(i+1);
                }
                stack.push(newstr);
            }

        }

    }

这是一个C解:

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


char* addLetter(char* string, char *c) {
    char* result = malloc(sizeof(string) + 2);
    strcpy(result, string);
    strncat(result, c, 1);
    return result;
}

char* removeLetter(char* string, char *c) {
    char* result = malloc(sizeof(string));
    int j = 0;
    for (int i = 0; i < strlen(string); i++) {
        if (string[i] != *c) {
            result[j++] = string[i];
        }
    }
    result[j] = '\0';

    return result;
}

void makeAnagram(char *anagram, char *letters) {

    if (*letters == '\0') {
        printf("%s\n", anagram);
        return;
    }

    char *c = letters;
    while (*c != '\0') {
        makeAnagram(addLetter(anagram, c),
                    removeLetter(letters, c));
        c++;
    }

}

int main() {

    makeAnagram("", "computer");

    return 0;
}

我们可以用阶乘来计算有多少字符串以某个字母开头。

示例:取输入abcd。(3!) == 6个字符串将以abcd中的每个字母开头。

static public int facts(int x){
    int sum = 1;
    for (int i = 1; i < x; i++) {
        sum *= (i+1);
    }
    return sum;
}

public static void permutation(String str) {
    char[] str2 = str.toCharArray();
    int n = str2.length;
    int permutation = 0;
    if (n == 1) {
        System.out.println(str2[0]);
    } else if (n == 2) {
        System.out.println(str2[0] + "" + str2[1]);
        System.out.println(str2[1] + "" + str2[0]);
    } else {
        for (int i = 0; i < n; i++) {
            if (true) {
                char[] str3 = str.toCharArray();
                char temp = str3[i];
                str3[i] = str3[0];
                str3[0] = temp;
                str2 = str3;
            }

            for (int j = 1, count = 0; count < facts(n-1); j++, count++) {
                if (j != n-1) {
                    char temp1 = str2[j+1];
                    str2[j+1] = str2[j];
                    str2[j] = temp1;
                } else {
                    char temp1 = str2[n-1];
                    str2[n-1] = str2[1];
                    str2[1] = temp1;
                    j = 1;
                } // end of else block
                permutation++;
                System.out.print("permutation " + permutation + " is   -> ");
                for (int k = 0; k < n; k++) {
                    System.out.print(str2[k]);
                } // end of loop k
                System.out.println();
            } // end of loop j
        } // end of loop i
    }
}

这可以通过简单地在前面部分结果的所有位置依次插入字符串的每个字母来迭代完成。

我们以[A]开头,与B连成[BA, AB],与C连成[CBA, BCA, BAC, CAB等]。

运行时间将是O(n!),对于测试用例ABCD,它是1 x 2 x 3 x 4。

在上面的乘积中,1是A, 2是B,以此类推。

飞镖示例:

void main() {

  String insertAt(String a, String b, int index)
  {
    return a.substring(0, index) + b + a.substring(index);
  }

  List<String> Permute(String word) {

    var letters = word.split('');

    var p_list = [ letters.first ];

    for (var c in letters.sublist(1)) {

      var new_list = [ ];

      for (var p in p_list)
        for (int i = 0; i <= p.length; i++)
          new_list.add(insertAt(p, c, i));

      p_list = new_list;
    }

    return p_list;
  }

  print(Permute("ABCD"));

}

使用递归的简单python解决方案。

def get_permutations(string):

    # base case
    if len(string) <= 1:
        return set([string])

    all_chars_except_last = string[:-1]
    last_char = string[-1]

    # recursive call: get all possible permutations for all chars except last
    permutations_of_all_chars_except_last = get_permutations(all_chars_except_last)

    # put the last char in all possible positions for each of the above permutations
    permutations = set()
    for permutation_of_all_chars_except_last in permutations_of_all_chars_except_last:
        for position in range(len(all_chars_except_last) + 1):
            permutation = permutation_of_all_chars_except_last[:position] + last_char + permutation_of_all_chars_except_last[position:]
            permutations.add(permutation)

    return permutations