寻找一个整数的正确后代

问题描述

我被一个基本的算法问题困住了,我不知道如何解决它。

基本上我想列出所有作为整数正确后代的数字。也就是说,如果我的数字是21,我想用它的二进制表示(10101),列出所有至少有一个值1和21的公共位并且小于21的数字。这里的结果应该是10100, 10001、10000、101、100、1。

适当后代的数学定义如下:

  • 设 h 是一个小于 2^m 的非负数。 h = d0 + d1*2^1 + ... + dm-1*2^(m-1) 其中 di = 0 或 1。

  • 设 h' 是另一个非负数,例如 h' = d0' + d1'*2^1 + ... + dm-1'*2^(m-1) 其中 di' = 0 或 1。

  • h' 是 h 的后代,如果 di'

我在 Python 和 C 中尝试了许多实现,并尝试了旧的纸笔技术,但都失败了。我知道这很简单,但我似乎无法弄清楚。我正在使用 C 进行编码,因此如果您找到一个适用于 C 的理想解决方案,那将是理想的,但我现在会采取任何措施。

解决方法

这是一个非常简单的方法:枚举 n-11 之间的所有整数,并打印那些严格包含在 n 中的整数,即:(i & n) == i

void list_descendants(int n) {
    printf("descendants of %d:",n);
    for (int i = n; i --> 1;) {
        if ((i & n) == i)
            printf(" %d",i);
    }
    printf("\n");
}
,

好的,所以我终于想出了一个 C 代码,它看起来并不好看,而且可能经过了可怕的优化,但仍然可以按预期工作。可能有更简单的解决方案,但这是我的知识目的:

#include <stdio.h>
#include <stdbool.h>
#include <stdlib.h>
unsigned int pui(unsigned int a,unsigned int b)
{
  if (b == 0)
    return 1;
  if (b == 1)
    return a;
  if (b % 2 == 0)
    return pui(a * a,b / 2);
  else
    return pui(a * a,(b - 1) / 2);
}
unsigned int testBit(unsigned int h,unsigned int offset)
{
  unsigned int mask = 1 << offset;
  return (h & mask);
}

bool isInList(unsigned int x,unsigned int *output_size,unsigned int **output)
{
  for (int i = 0; i < *output_size; i++)
  {
    if (*(*output + i) == x)
    {
      return true;
    }
  }
  return false;
}
void listDescendants(unsigned int h,unsigned int **output,int *currently_processing)
{
  unsigned int max_offset = 0;
  unsigned int temp_h = h;
  unsigned int initial_output_size = *output_size;
  while (temp_h > 0)
  {
    max_offset++;
    temp_h /= 2;
  }
  unsigned int h_radix2[max_offset];
  for (int i = 0; i < max_offset; i++)
  {
    if (testBit(h,i))
    {

      if (h > pui(2,i) && !isInList(h - pui(2,i),output_size,output))
      {
        *(*output + *output_size) = h - pui(2,i);
        *output_size += 1;
      }
    }
  }

  if (*currently_processing < (int)*output_size)
  {
    *currently_processing += 1;
    listDescendants(*(*output + *currently_processing),output,currently_processing);
  }
}


int main()
{
  
  int currently_processing = -1;
  unsigned int size = 0;
  unsigned int *output = malloc(300 * sizeof(unsigned int));
  listDescendants(21,&size,&output,&currently_processing);

  printf("size = %u\n",size);
  for (int i = 0; i < size; i++)
  {
    printf("%u ",output[i]);
  }
  printf("\n");

  return 0;
}
,

您可以使用递归解决方案,例如以下解决方案。

我有点懒,所以我没有把数字放在列表中而是简单地打印出来,我还打印了0和给定的数字。

我相信您可以轻松调整代码,使其按您的意愿行事。

#include <stdio.h>

#define CHAR_BIT 8

void ProperDescendantsRecursive(unsigned int num,unsigned int bit_index)
{
    if (CHAR_BIT * sizeof(unsigned int) - 1 == bit_index)
    {
        printf("%u\n",num);
    }
    else
    {
        unsigned int mask = 1U << bit_index;
        if (num & mask)
        {
            /* with the bit at index bit_index is off */
            ProperDescendantsRecursive(num ^ mask,bit_index + 1);
            /* with the bit at index bit_index is on */
            ProperDescendantsRecursive(num,bit_index + 1);
        }
        else
        {
            ProperDescendantsRecursive(num,bit_index + 1);
        }
    }
}

void ProperDescendants(unsigned int num)
{
    ProperDescendantsRecursive(num,0);
}

int main(void)
{
    ProperDescendants(21);
    
    return 0;
}

编译和运行结果如下:

0
16
4
20
1
17
5
21

相关问答

Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其...
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。...
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbc...