【问题标题】:Finding all subsets of a set, a DP solution?找到一个集合的所有子集,一个 DP 解决方案?
【发布时间】:2016-05-10 15:27:13
【问题描述】:

我遇到了寻找集合子集的问题,我想知道我的算法是否正确。我正在使用递归方法和哈希表来存储已经计算的子集并说输入字符串是“ABCD”:

1) 我的方法是将单个字符添加为哈希键,并将键的子集作为值计算。例如,在我的哈希表中,给定输入字符串的“B”条目看起来像“B”、“BC”、“BD”、“BCD”。调用堆栈的函数然后将使用这些子字符串来形成进一步的子集。例如“AB”、“ABC”、“ABD”、“ABCD”。

2) 我使用 for 循环遍历剩余的字符并检查给定字符的子集是否在哈希表中,如果不是,我递归并形成子集并存储它们。

这个算法的想法是我不必重新计算已经看到的子集,然后截断后续的函数调用。例如 A->C、A->D,因为 C 和 D 的所有子集都是在执行“B”中的 for 循环时计算的。

我的记忆算法正确吗? 即使在我记忆之后,运行时间也会是 O(2^n) 吗?预先感谢您的回复。如果我在任何地方犯了错误,请原谅我,您的 cmets 一定会帮助我改进。再次感谢!

【问题讨论】:

  • 运行时间不能小于 O(2^n),因为有 2^n 个子集。
  • 没有什么可以“找到” IMO,它已经知道所有子集是什么。您可以决定枚举它们(就像您所做的那样),但这相当于从 0 计数到 (2^n)-1。

标签: algorithm dynamic-programming memoization


【解决方案1】:

您的记忆算法似乎正确。但复杂度大于 O(2^n) 并且取决于您的哈希函数。

这是一个 NP 完全问题。如果 n 的大小很大,那么你就无法记住。但是如果 n 很小(比如 20),那么你可以使用 dp(Bitmasking+dp) 来解决这种问题。

我在下面展示了迭代的想法。

for(i=0;i<(1<<n);i++){
   subset=""
   for(j=0;j<n;j++){
      if( (i&(1<<j)) != 0 ) //if jth character of binary i is 1, then add jth item 
        add jth item to subset
   }
   print(subset)

}

【讨论】:

    【解决方案2】:
        import java.util.ArrayList;
        import java.util.Arrays;
        import java.util.List;
    
        public class MainClass {
    
            static List<List<char[]>> list = new ArrayList<List<char[]>>();
    
            // static List<int[]> list1 = new ArrayList<int[]>();
            public static void main(String[] args) {
                List<char[]> list1 = new ArrayList<char[]>();
                char[] a = {'A','B','C','D'};
                generate(a, 0, 0, list1);
    
                for (List<char[]> l : list) {
                    for (char[] b : l) {
                        for (char c : b) {
                            System.out.print(c + ",");
                        }
                        System.out.println();
                    }
                }
    
            }
    
            public static void generate(char[] array, int offset, int index, List<char[]> list1) {
                if (offset >= array.length)
                    return;
                char[] newArray = Arrays.copyOfRange(array, offset, index);
                list1.add(newArray);
                if (index >= array.length) {
                    list.add(list1);
                    offset++;
                    index = offset;
                    generate(array, offset, index, new ArrayList<char[]>());
                } else {
                    index++;
                    generate(array, offset, index, list1);
                }
            }
        }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2023-03-19
      • 1970-01-01
      • 2016-08-13
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-11-19
      • 2019-06-21
      相关资源
      最近更新 更多