Java 无回路递归发电机组

Java 无回路递归发电机组,java,algorithm,recursion,Java,Algorithm,Recursion,如何编写递归方法PowerSet(stringinput),输出传递给它的字符串的所有可能组合 例如:PowerSet(“abc”)将打印出abc、ab、ac、bc、a、b、c 我见过一些带有循环的递归解决方案,但在这种情况下不允许循环 有什么想法吗 编辑:所需的方法只有一个参数,即字符串输入。如果没有循环,请使用迭代器使用递归模拟循环。这实际上非常简单 public final Set<Set<Integer>> powerSet(Set<Integer&

如何编写递归方法PowerSet(stringinput),输出传递给它的字符串的所有可能组合

例如:PowerSet(“abc”)将打印出abc、ab、ac、bc、a、b、c

我见过一些带有循环的递归解决方案,但在这种情况下不允许循环

有什么想法吗


编辑:所需的方法只有一个参数,即字符串输入。

如果没有循环,请使用迭代器使用递归模拟循环。这实际上非常简单

    public final Set<Set<Integer>> powerSet(Set<Integer> set) {
        Set<Set<Integer>> powerSet = new HashSet<>();
        powerSet(set, powerSet, set.iterator());
        return powerSet;
    }
    public final void powerSet(Set<Integer> set, Set<Set<Integer>> powerSet, Iterator<Integer> iterator) {
        if(iterator.hasNext()) {
            Integer exlude = iterator.next();
            Set<Integer> powThis = new HashSet<Integer>();
            powThis.addAll(set);
            powThis.remove(exlude);
            powerSet.add(powThis);
            powerSet(powThis, powerSet, powThis.iterator());
            powerSet(set, powerSet, iterator);
        }
    }
//usage
        Set<Integer> set = new HashSet<>();
        set.add(1);
        set.add(2);
        set.add(3);
        set.add(4);
        log.error(powerSet(set).toString());
公共最终设定功率集(设定){
Set powerSet=new HashSet();
powerSet(set,powerSet,set.iterator());
返回动力装置;
}
公共最终void powerSet(Set Set、Set powerSet、迭代器迭代器){
if(iterator.hasNext()){
整数exlude=iterator.next();
Set powThis=new HashSet();
powThis.addAll(set);
移除(排除);
powerSet.add(powThis);
powerSet(powThis,powerSet,powThis.iterator());
powerSet(set、powerSet、迭代器);
}
}
//用法
Set=newhashset();
增加(1);
增加(2);
增加(3);
增加(4);
log.error(powerSet(set).toString());

的电源集是
abc
abd
acd
(加上电源集本身*)的电源集的联合

*请注意,作为p(abcd)成员的空集也是p(abc)、p(abd)的成员。。。因此,上述等价性成立

递归地,p(
abc
)={
abc
}+p(
ab
)+p(
ac
),依此类推

在伪代码中,第一种方法可以是:

powerset(string) {
  add string to set;
  for each char in string {
   let substring = string excluding char,
   add powerset(substring) to set
  }
  return set;      
}
当字符串为空时,递归结束(因为它从未进入循环)

如果您确实想要循环,则必须将该循环转换为另一个递归。 现在我们想从
abc
生成
ab
ac
cb

powerset(string) {
  add string to set;
  add powerset2(string,0) to set;
  return set
}

powerset2(string,pos) {
  if pos<length(string) then
    let substring = (string excluding the char at pos)
    add powerset(substring) to set
    add powerset2(string,pos+1) to set
  else 
    add "" to set
  endif
  return set
}
然后

如果允许循环,则
p
是输出功率设置功能。否则,我们将需要一个单参数无环函数来将给定的字符连接到给定的字符串集(这显然是两个东西)


通过使用
String.replace
(如果需要
String
结果,或者通过将
Set
替换为
List
(这样“附加”参数实际上是列表中的第一个元素)可以进行一些调整。

建议的递归版本:


这也可以做到:

var powerset = function(arr, prefix, subsets) {
  subsets = subsets || [];
  prefix = prefix || [];
  if (arr.length) {
    powerset(arr.slice(1), prefix.concat(arr[0]), subsets);
    powerset(arr.slice(1), prefix, subsets);
  } else {
    subsets.push(prefix);
  }
  return subsets;
};

powerset('abc');
void powerSet(int*ar、int*temp、int-n、int-level、int-index)
{
如果(指数=n)返回;
int i,j;

对于(i=index;i简单但时间复杂度较差的解决方案(2^n),如下所示(只要记住一件事,一旦我们必须避免(即0),一旦我们必须采取(即1):

public HashSet powerSet(int n){
返回calcPowerSet(n-1,newhashset(),newint[n]);
}
私有HashSet-calcPowerSet(int n,HashSet-result,int[]set){
if(n<0){
result.add(set.clone());
返回null;
}
否则{
设置[n]=0;
calcPowerSet(n-1,结果,集合);
设置[n]=1;
calcPowerSet(n-1,结果,集合);
返回结果;
}
}

只是为了好玩,这个版本不支持存储在
链接列表中的任何集的powerset(以便于删除head元素)。Java 8 streams完成以下功能部分:

static <T> LinkedList<LinkedList<T>> powerset(LinkedList<T> elements) {
  if (elements.isEmpty()) 
    return copyWithAddedElement(new LinkedList<>(), new LinkedList<>());
  T first = elements.pop();
  LinkedList<LinkedList<T>> powersetOfRest = powerset(elements);
  return Stream.concat(
      powersetOfRest.stream(), 
      powersetOfRest.stream().map(list -> copyWithAddedElement(list, first)))
          .collect(Collectors.toCollection(LinkedList::new));
}

static <T> LinkedList<T> copyWithAddedElement(LinkedList<T> list, T elt) {
  list = new LinkedList<>(list);
  list.push(elt);
  return list;
}
根据这些信息,这里是C#中的解决方案

注意:main函数中的循环只是将结果打印到控制台值中。PowerSet方法中不使用循环

    public static void Main(string[] args)
    {

        string input = "abbcdd";


        Dictionary < string, string> resultSet = new Dictionary<string, string>();

        PowerSet(input, "", 0, resultSet);

        //apply sorting 
        var resultSorted = resultSet.OrderBy(l => l.Key.Length).ThenBy(l=>l.Key);

        //print values
        foreach(var keyValue in resultSorted)
        {
            Console.Write("{{{0}}}, ",keyValue.Key);
        }


    }

    /// <summary>
    /// Computes the powerset of a string recursively
    /// based on the Algorithm http://www.ideserve.co.in/learn/generate-all-subsets-of-a-set-recursion
    /// </summary>
    /// <param name="input">Original input string</param>
    /// <param name="temp">Temporary variable to store the current char for the curr call</param>
    /// <param name="depth">The character position we are evaluating to add to the set</param>
    /// <param name="resultSet">A hash list to store the result</param>
    public static void PowerSet(string input, string temp, int depth, Dictionary<string, string> resultSet)
    {

        //base case
        if(input.Length == depth)
        {
            //remove duplicate characters
            string key = new string(temp.ToCharArray().Distinct().ToArray());

            //if the character/combination is already in the result, skip it
            if (!resultSet.ContainsKey(key))
                resultSet.Add(key, key);

            return;//exit 
        }

        //left
        PowerSet(input, temp, depth + 1, resultSet);

        //right
        PowerSet(input, temp + input[depth], depth + 1, resultSet);

    }
publicstaticvoidmain(字符串[]args)
{
字符串输入=“abbcdd”;
DictionaryresultSet=newdictionary();
电源集(输入“”,0,结果集);
//应用排序
var resultSorted=resultSet.OrderBy(l=>l.Key.Length),然后是by(l=>l.Key);
//打印值
foreach(resultSorted中的var keyValue)
{
Write(“{{{0}}},”,keyValue.Key);
}
}
/// 
///递归计算字符串的功率集
///基于该算法http://www.ideserve.co.in/learn/generate-all-subsets-of-a-set-recursion
/// 
///原始输入字符串
///用于存储curr调用的当前字符的临时变量
///要添加到集合中的角色位置
///存储结果的哈希列表
公共静态void PowerSet(字符串输入、字符串临时值、int深度、字典结果集)
{
//基本情况
if(input.Length==深度)
{
//删除重复字符
字符串键=新字符串(临时ToCharArray().Distinct().ToArray());
//如果结果中已包含该字符/组合,请跳过它
如果(!resultSet.ContainsKey(键))
结果集添加(键,键);
return;//退出
}
//左
功率集(输入、温度、深度+1、结果集);
//对
功率集(输入,温度+输入[深度],深度+1,结果集);
}

这种情况?哪种情况?我认为有一些算法可以解决这个问题,以防你用谷歌搜索。几乎每个循环都可以被递归函数替换。@R.J.我的意思是,在这种情况下,不允许循环。这是问题的要求。@Matten我找到了一些,但大多数都不是正确的f这是因为它们有不止一个参数。实际上,您有不止一个参数:
String.getBytes();
Awesome,我确实想到了伪代码中的算法。但我在执行此任务时遇到了困难:让substring=String,不包括char。API中有内置函数可以做到这一点吗?
s.substring(0,pos)
将子字符串从
0
返回到
public static <T> Set<Set<T>> powerSet2(Set<T> originalSet) {
    Set<Set<T>> sets = new HashSet<Set<T>>();
    if (originalSet.isEmpty()) {
        sets.add(new HashSet<T>());
        return sets;
    }
    List<T> list = new ArrayList<T>(originalSet);
    T head = list.get(0);
    Set<T> rest = new HashSet<T>(list.subList(1, list.size()));
    addSets(sets, powerSet(rest), head);
    return  sets;
}

private static <T> void addSets(Set<Set<T>> sets, Set<Set<T>> setsToAdd, T head) {
    Iterator<Set<T>> iterator = setsToAdd.iterator();
    if (iterator.hasNext()) {
        Set<T> set = iterator.next();
        iterator.remove();
        Set<T> newSet = new HashSet<T>();
        newSet.add(head);
        newSet.addAll(set);
        sets.add(newSet);
        sets.add(set);
        addSets(sets, setsToAdd, head);
    }
}
for (Set<T> set : powerSet(rest)) {
    Set<T> newSet = new HashSet<T>();
    newSet.add(head);
    newSet.addAll(set);
    sets.add(newSet);
    sets.add(set);
}
var powerset = function(arr, prefix, subsets) {
  subsets = subsets || [];
  prefix = prefix || [];
  if (arr.length) {
    powerset(arr.slice(1), prefix.concat(arr[0]), subsets);
    powerset(arr.slice(1), prefix, subsets);
  } else {
    subsets.push(prefix);
  }
  return subsets;
};

powerset('abc');
void powerSet(int * ar, int *temp, int n, int level,int index)
{
    if(index==n) return;

    int i,j;
    for(i=index;i<n;i++)
    {
    temp[level]=ar[i];

    for(j=0;j<=level;j++)
    printf("%d ",temp[j]);
    printf("   - - -  t\n");

    powerSet(ar, temp, n, level+1,i+1);
    }
}

int main()
{
    int price[] = {1,2,3,7};
    int temp[4] ={0};

    int n = sizeof(price)/sizeof(price[0]);

    powerSet(price, temp, n, 0,0);


    return 0;
}
public HashSet<int[]> powerSet(int n) {
    return calcPowerSet(n-1, new HashSet<int[]>(), new int[n]);
}

private HashSet<int[]> calcPowerSet(int n, HashSet<int[]> result, int []set) {
    if(n < 0) {
        result.add(set.clone());
        return null;
    }
    else {
        set[n] = 0;
        calcPowerSet(n-1, result, set);
        set[n] = 1;
        calcPowerSet(n-1, result, set);
        return result;
    }
}
static <T> LinkedList<LinkedList<T>> powerset(LinkedList<T> elements) {
  if (elements.isEmpty()) 
    return copyWithAddedElement(new LinkedList<>(), new LinkedList<>());
  T first = elements.pop();
  LinkedList<LinkedList<T>> powersetOfRest = powerset(elements);
  return Stream.concat(
      powersetOfRest.stream(), 
      powersetOfRest.stream().map(list -> copyWithAddedElement(list, first)))
          .collect(Collectors.toCollection(LinkedList::new));
}

static <T> LinkedList<T> copyWithAddedElement(LinkedList<T> list, T elt) {
  list = new LinkedList<>(list);
  list.push(elt);
  return list;
}
(defun powerset (set)
  (cond ((null set) '(()))
        (t (let ((powerset-of-rest (powerset (cdr set))))
          (append powerset-of-rest
                  (mapcar #'(lambda (x) (cons (car set) x)) 
                          powerset-of-rest))))))
    public static void Main(string[] args)
    {

        string input = "abbcdd";


        Dictionary < string, string> resultSet = new Dictionary<string, string>();

        PowerSet(input, "", 0, resultSet);

        //apply sorting 
        var resultSorted = resultSet.OrderBy(l => l.Key.Length).ThenBy(l=>l.Key);

        //print values
        foreach(var keyValue in resultSorted)
        {
            Console.Write("{{{0}}}, ",keyValue.Key);
        }


    }

    /// <summary>
    /// Computes the powerset of a string recursively
    /// based on the Algorithm http://www.ideserve.co.in/learn/generate-all-subsets-of-a-set-recursion
    /// </summary>
    /// <param name="input">Original input string</param>
    /// <param name="temp">Temporary variable to store the current char for the curr call</param>
    /// <param name="depth">The character position we are evaluating to add to the set</param>
    /// <param name="resultSet">A hash list to store the result</param>
    public static void PowerSet(string input, string temp, int depth, Dictionary<string, string> resultSet)
    {

        //base case
        if(input.Length == depth)
        {
            //remove duplicate characters
            string key = new string(temp.ToCharArray().Distinct().ToArray());

            //if the character/combination is already in the result, skip it
            if (!resultSet.ContainsKey(key))
                resultSet.Add(key, key);

            return;//exit 
        }

        //left
        PowerSet(input, temp, depth + 1, resultSet);

        //right
        PowerSet(input, temp + input[depth], depth + 1, resultSet);

    }