生成系列{1,3,9,27,...}的子集,并按照递增的顺序对子集进行排序

时间:2015-02-16 09:35:41

标签: java algorithm numbers set

我被要求生成3次幂集{1,3,9,27,81,....}的子集,然后按其总和的递增顺序排列子集,例如{{},{ 1} ,, {3},{1,3},{9},{1,9},{3,9},{1,3,9},..........}。最后,当用户输入n时,我们需要打印第n个子集,例如,如果n = 4,则解是第三个子集{1,3}。 n的范围基本上非常大。

我怀疑是:

  1. 我们如何达到主要设定的上限。
  2. 我应该使用哪种数据结构
  3. 除暴力之外还有其他方法。

5 个答案:

答案 0 :(得分:2)

对于这个问题,3的幂或2的幂是相同的,但是更容易看到具有2的幂的解。见序列:

  • {}总和:0
  • {1}总和:1
  • {2}总和:2(二进制10)
  • {1,2} sum:3(二进制11)
  • {4}总和:4(二进制100)
  • {4,1}总和:5(二进制101)
  • {4,2} sum:6(二进制110)

因此,解决方案是以二进制计数然后解释基数为3的给定数字。例如:

  • 0 - > {}
  • 1 - > 3 ^ 0 - > {1}
  • 10 - > 3 ^ 1 - > {3}
  • 11 - > 3 ^ 1,3 ^ 0 - > {3,1}
  • 100 - > 3 ^ 2 - > {9}
  • 101 - > 3 ^ 2,3 ^ 0 - > {9,1}
  • 110 - > 3 ^ 2,3 ^ 1 - > {9,3}
  • 111 - > 3 ^ 2,3 ^ 1,3 ^ 0 - > {9,3,1}
  • 1000 - > 3 ^ 3 - > {27}

因此,对于给定的n,将其转换为二进制,然后再转换为三元组。

这是代码

private static String calc(int n) {
  String binary = Integer.toString(n - 1, 2);
  String reverse = new StringBuilder(binary).reverse().toString();

  StringBuilder sb = new StringBuilder();
  sb.append("{");
  for (int i = 0; i < reverse.length(); i++) {
    if(reverse.charAt(i) == '1') {
      sb.append(BigInteger.valueOf(3).pow(i)).append(" ");
    }
  }
  //remove last space
  if(sb.length() != 1) { sb.deleteCharAt(sb.length() -1); }
  sb.append("}");
  return sb.toString();
}

测试

for(int i = 1; i<=10; i++) {
  System.out.println(calc(i));
}

结果

{}
{1}
{3}
{1 3}
{9}
{1 9}
{3 9}
{1 3 9}
{27}
{1 27}

答案 1 :(得分:0)

  1. 您不首先创建大量子集,然后对其进行排序。您可以按已排序的顺序创建子集(这是算法的关键部分)。然后,当您创建&#39; n&#39;子集。
  2. 你需要自己做。如果我没记错的话,我只是在制作类似的东西时使用队列。
  3. 不是我所知道的。问题是你需要订购子集,这不是一件容易的事。

答案 2 :(得分:0)

  

除了蛮力外,还有其他方法。

是的。尝试生成有序的集合序列。我们可以证明这将使用归纳法。

  1. 最小总和为{}

  2. 假设您已经订购了包含N的数字的所有子集。

  3. 要生成包含N的所有子集,只需将N添加到步骤2中的每个集合(按相同顺序)

  4. 这将起作用,因为以下情况属实 - 3 ^ n&gt; 3 ^ n-1 + 3 ^ n-2 ....例如,子集sum({3 ^ n})大于仅包含3 ^ n-1和更小元素的所有子集的总和。

    示例

    1. {1}是最小的子集
    2. {},{1},{3},{1,3},{9},{1,9},{3,9},{1,3,9} - 包含数字少的有序子集比9
    3. {},{1},{3},{1,3},{9},{1,9},{3,9},{1,3,9},{27},{1 ,27},{3,27},{9,27} .... {1,3,9,27} - 包含数字小于27的有序子集

答案 3 :(得分:0)

我们只需要将给定的'n'转换为二进制,然后提高 3 ^ i 的幂(仅当第i位为 setbit ),因为只有setbit会贡献子集。

这将因以下条件而起作用:(3 ^ n> 3 ^ n-1 + 3 ^ n-2) 例如:3 ^ 2> 3 ^ 1 + 3 ^ 0

现在的代码:

void decimalToBinary(long int n) 
{ 
int binaryNum[32];                        // array to store binary number  
int i = 0;                                // counter for binary array
while (n > 0) {                           // storing remainder in binary array
    binaryNum[i] = n % 2; 
    n = n / 2; 
    i++; 
} 
for (int j = 0; j <i; j++) 
{
    if(binarray[j]==1)
        cout<<binpower(3,j)<<" ";              //must be binary exponentiation
}
} 

输入:6

输出:3 9

答案 4 :(得分:0)

很容易看出,如果以n的二进制表示形式设置了第i位,则可以通过打印集合S的第i个元素来生成子集,如果不设置该位,则不打印任何内容。 / p>

  1. 初始化count = 0和x = 0
  2. 用于存储子集元素的向量
  3. 执行以下操作,直到n退出
    • set x = n&1 //用于查找是否设置了最后一位
    • 如果x不为零,请执行此操作
      • 按pow(3,count)将向量中的元素推入
    • 然后对n(n = n >> 1)右移
    • 将计数值增加1
  4. 最后打印出向量的元素