【问题标题】:All Unique Permutations - Stack overflow issue所有唯一排列 - 堆栈溢出问题
【发布时间】:2016-10-15 09:40:29
【问题描述】:

我正在尝试解决以下问题:

给定一组可能包含重复的数字,返回 所有可能的唯一排列。

这是我的代码:

public class Solution {
    public ArrayList<ArrayList<Integer>> permute(ArrayList<Integer> a) {
        HashMap<ArrayList<Integer>, Boolean> unique = new HashMap<>();
        ArrayList<ArrayList<Integer>> results = new ArrayList<>();
        permu(results, a, 0, unique);
        return results;
    }

    private void permu(ArrayList<ArrayList<Integer>> results, final ArrayList<Integer> a, int item, HashMap<ArrayList<Integer>, Boolean> unique) {
        for(int i = 0; i < a.size(); i++) {
            ArrayList<Integer> aClone = new ArrayList<>(a);
            // swap
            int backup = aClone.get(i);
            aClone.set(i, aClone.get(item));
            aClone.set(item, backup);
            if(!unique.containsKey(aClone)) {
                results.add(aClone);
                unique.put(aClone, true);
                permu(results, aClone, i, unique); //<--- Stack overflow error
            }

        }
    }
}

我在调用循环时遇到堆栈溢出错误,第 (19) 行

【问题讨论】:

  • 你能在发生 stackoverflow 错误的行旁边写一个注释吗?在这里计算行号对我们来说不太实用。
  • 确定 > permu(results, aClone, i, unique);
  • 问题已编辑
  • 你每次都是从0开始。我想你的意思是int i = item;
  • 这是为了某种编码竞赛,对吧?诀窍在于其中一项测试包含一个整数,该整数出现 许多 次......可能产生和检查所有 n 的次数如此之多!即使没有溢出堆栈,排列也会超时。

标签: java algorithm stack-overflow


【解决方案1】:

好吧,我不喜欢破坏好工作的面试问题,但是这个问题很有趣,所以......

这是一个超级 L337 的答案,可以非常快速地生成所有独特的排列,而无需使用太多内存或堆栈。如果你在求职面试中使用它,面试官会要求你解释它是如何工作的。如果你能做到这一点,那么你应该得到它:)

请注意,我在字符串中置换了字符而不是列表中的整数,只是因为更容易漂亮地打印结果。

import java.util.Arrays;
import java.util.function.Consumer;


public class UniquePermutations
{
    static void generateUniquePermutations(String s, Consumer<String> consumer)
    {
        char[] array = s.toCharArray();
        Arrays.sort(array);
        for (;;)
        {
            consumer.accept(String.valueOf(array));

            int changePos=array.length-2;
            while (changePos>=0 && array[changePos]>=array[changePos+1])
                --changePos;

            if (changePos<0)
                break; //all done

            int swapPos=changePos+1;
            while(swapPos+1 < array.length && array[swapPos+1]>array[changePos])
                ++swapPos;

            char t = array[changePos];
            array[changePos] = array[swapPos];
            array[swapPos] = t;

            for (int i=changePos+1, j = array.length-1; i < j; ++i,--j)
            {
                t = array[i];
                array[i] = array[j];
                array[j] = t;
            }
        }
    }

    public static void main (String[] args) throws java.lang.Exception
    {
        StringBuilder line = new StringBuilder();
        generateUniquePermutations("banana", s->{
            if (line.length() > 0)
            {
                if (line.length() + s.length() >= 75)
                {
                    System.out.println(line.toString());
                    line.setLength(0);
                }
                else
                    line.append(" ");
            }
            line.append(s);
        });
        System.out.println(line);
    }
}

这是输出:

aaabnn aaanbn aaannb aabann aabnan aabnna aanabn aananb aanban aanbna
aannab aannba abaann abanan abanna abnaan abnana abnnaa anaabn anaanb
anaban anabna ananab ananba anbaan anbana anbnaa annaab annaba annbaa
baaann baanan baanna banaan banana bannaa bnaaan bnaana bnanaa bnnaaa
naaabn naaanb naaban naabna naanab naanba nabaan nabana nabnaa nanaab
nanaba nanbaa nbaaan nbaana nbanaa nbnaaa nnaaab nnaaba nnabaa nnbaaa

【讨论】:

  • 谢谢你,Matt,我会更深入地研究一下,你认为我的方法中的重复导致我正在考虑的问题吗?
  • 顺便说一句,是的,我认为这是一个非常有趣的问题
  • @JeromeAnsia,当你递归调用permu时,你应该传递item+1而不是i,并在item>=a.size()时停止递归。您还应该在i = item 开始for 循环。你写它的方式,你用相同的参数无限递归
猜你喜欢
  • 2010-10-15
  • 2017-05-02
  • 2020-06-19
  • 2019-05-18
  • 1970-01-01
  • 2022-10-09
  • 1970-01-01
  • 1970-01-01
  • 2016-06-27
相关资源
最近更新 更多