当前位置: 首页 > 知识库问答 >
问题:

使用迭代的字符串排列

公孙成仁
2023-03-14

我试图找到给定字符串的排列,但我想使用迭代。我在网上找到的递归解决方案,我确实理解它,但是将其转换为迭代解决方案真的行不通。下面我附上了我的代码。我真的很感激你的帮助:

public static void combString(String s) {
    char[] a = new char[s.length()];
    //String temp = "";
    for(int i = 0; i < s.length(); i++) {
        a[i] = s.charAt(i);
    }
    for(int i = 0; i < s.length(); i++) {
        String temp = "" + a[i];    

        for(int j = 0; j < s.length();j++) {
            //int k = j;
            if(i != j) {
                System.out.println(j);
                temp += s.substring(0,j) + s.substring(j+1,s.length());
            }               
        }
        System.out.println(temp);
    }
}

共有3个答案

吴刚毅
2023-03-14

工作队列允许我们为这个问题创建一个优雅的迭代解决方案

static List<String> permutations(String string) {
    List<String> permutations = new LinkedList<>();
    Deque<WorkUnit> workQueue = new LinkedList<>(); 

    // We need to permutate the whole string and haven't done anything yet.
    workQueue.add(new WorkUnit(string, ""));

    while (!workQueue.isEmpty()) { // Do we still have any work?
        WorkUnit work = workQueue.poll();

        // Permutate each character.
        for (int i = 0; i < work.todo.length(); i++) {
            String permutation = work.done + work.todo.charAt(i);

            // Did we already build a complete permutation?
            if (permutation.length() == string.length()) {
                permutations.add(permutation);
            } else {

                // Otherwise what characters are left? 
                String stillTodo = work.todo.substring(0, i) + work.todo.substring(i + 1);
                workQueue.add(new WorkUnit(stillTodo, permutation));
            }
        }
    }
    return permutations; 
}

用于保存部分结果的帮助程序类非常简单。

/**
 * Immutable unit of work
 */
class WorkUnit {
    final String todo;
    final String done;

    WorkUnit(String todo, String done) {
        this.todo = todo;
        this.done = done;
    }
}

您可以通过将上述代码包装在此类中来测试它们。

import java.util.*;

public class AllPermutations {

    public static void main(String... args) {
        String str = args[0];
        System.out.println(permutations(str));
    }

    static List<String> permutations(String string) {
        ...
    }
}

class WorkUnit {
    ...
}

通过编译和运行来尝试。

$ javac AllPermutations.java; java AllPermutations abcd

通过使用后进先出(LIFO)工作堆栈而不是FIFO队列,下面的实现也可以很容易地调整为以相反的顺序返回排列列表。

颜祖鹤
2023-03-14
    List<String> results = new ArrayList<String>();
    String test_str = "abcd";
    char[] chars = test_str.toCharArray();
    results.add(new String("" + chars[0]));
    for(int j=1; j<chars.length; j++) {
        char c = chars[j];
        int cur_size = results.size();
        //create new permutations combing char 'c' with each of the existing permutations
        for(int i=cur_size-1; i>=0; i--) {
            String str = results.remove(i);
            for(int l=0; l<=str.length(); l++) {
                results.add(str.substring(0,l) + c + str.substring(l));
            }
        }
    }
    System.out.println("Number of Permutations: " + results.size());
    System.out.println(results);

例如:如果我们有3个字符串,例如“abc”,我们可以形成如下排列。

1)构造一个带有第一个字符的字符串,例如“a”并将其存储在结果中。

    char[] chars = test_str.toCharArray();
    results.add(new String("" + chars[0]));

2) 现在取字符串中的下一个字符(即“b”),并将其插入到结果中先前构建的字符串的所有可能位置。由于此时结果中只有一个字符串(“a”),所以这样做会产生两个新字符串“ba”和“ab”。在结果中插入这些新构造的字符串并删除“a”。

    for(int i=cur_size-1; i>=0; i--) {
        String str = results.remove(i);
        for(int l=0; l<=str.length(); l++) {
            results.add(str.substring(0,l) + c + str.substring(l));
        }
    }

3)对给定字符串中的每个字符重复2)重复。

for(int j=1; j<chars.length; j++) {
    char c = chars[j];
     ....
     ....
}

这给了我们来自ba和cab的cba,bca,bac,来自ab的acb和abc

贺兴昌
2023-03-14

继续我的相关问题评论,这里有一个Java实现,它使用计数QuickPerm算法做您想要做的事情:

public static void combString(String s) {
    // Print initial string, as only the alterations will be printed later
    System.out.println(s);   
    char[] a = s.toCharArray();
    int n = a.length;
    int[] p = new int[n];  // Weight index control array initially all zeros. Of course, same size of the char array.
    int i = 1; //Upper bound index. i.e: if string is "abc" then index i could be at "c"
    while (i < n) {
        if (p[i] < i) { //if the weight index is bigger or the same it means that we have already switched between these i,j (one iteration before).
            int j = ((i % 2) == 0) ? 0 : p[i];//Lower bound index. i.e: if string is "abc" then j index will always be 0.
            swap(a, i, j);
            // Print current
            System.out.println(join(a));
            p[i]++; //Adding 1 to the specific weight that relates to the char array.
            i = 1; //if i was 2 (for example), after the swap we now need to swap for i=1
        }
        else { 
            p[i] = 0;//Weight index will be zero because one iteration before, it was 1 (for example) to indicate that char array a[i] swapped.
            i++;//i index will have the option to go forward in the char array for "longer swaps"
        }
    }
}

private static String join(char[] a) {
    StringBuilder builder = new StringBuilder();
    builder.append(a);
    return builder.toString();
}

private static void swap(char[] a, int i, int j) {
    char temp = a[i];
    a[i] = a[j];
    a[j] = temp;
}
 类似资料:
  • 问题内容: 我正在尝试查找给定字符串的排列,但是我想使用迭代。我在网上找到了递归解决方案,但我确实理解它,但是将其转换为迭代解决方案实际上是行不通的。下面附上我的代码。我非常感谢您的帮助: 问题答案: 在我的相关问题评论之后,这是一个Java实现,可以使用Counting QuickPerm Algorithm 来完成您想要的事情:

  • 问题内容: 我有一个字符串迭代器。 为了进行排序,我需要从中创建一个列表并使用对其进行排序。 有没有简单的方法可以对迭代器进行排序。 问题答案: 迭代器不是容器,它是遍历容器元素的实用程序。因此,如果您仅有权访问迭代器,则无法更改此迭代器的创建者定义的迭代顺序。 如果您不能更改原始容器,则必须将迭代器传递的元素收集到新的Collection中,并在其中进行排序。 (了解迭代器可能的一种好方法是查看

  • 我阅读了这个简单而优雅的python解决方案,用于查找给定字符串的所有排列。它是递归的。基于此,我尝试用python实现一个迭代解决方案。 下面是我的代码。但它只适用于3个字符串:(试图了解递归基本情况条件和递归条件如何转化为迭代(非递归)任何指针将有助于获得迭代解决方案的工作。(基于此算法或任何其他算法)

  • 问题内容: 更新: 在2006年python.org上提出了使内置字符串不可迭代的想法。我的问题有所不同,因为我试图偶尔仅抑制一次此功能。整个线程还是很相关的。 这是Guido的批判性评论,他们在试用的基础上实施了不可重复的操作: […]我实现了这一点(这确实很简单),但是后来发现我不得不修复大量遍历字符串的地方。例如: sre解析器和编译器使用set(“ 0123456789”)之类的东西,并且

  • 我在名为的类中有一个链表,它包含以下属性: 我有另一个类,它是“实际列表”,它只包含对列表头部的引用,这个类被称为“文本列表”,它接收一个字符串,并假设将该字符串的每个单词排序在列表中。例如,对于句子: 链接列表如下所示: 箭头就像指向列表中下一个节点的指针。 我想先把所有的单词放在一个链表中(类),然后做一个MERGE SORT来对链表中的单词进行排序。 我想做的是采用拆分方法将列表拆分为两个列

  • NowCoder 题目描述 输入一个字符串,按字典序打印出该字符串中字符的所有排列。例如输入字符串 abc,则打印出由字符 a, b, c 所能排列出来的所有字符串 abc, acb, bac, bca, cab 和 cba。 解题思路 // java private ArrayList ret = new ArrayList<>(); public ArrayList Permutation(