找出连续的1的数字

3

我正在尝试找出二进制数中连续1的数量。

例如:将十进制数转换为二进制并查找连续的1。

static int count = 0;
static int max = 0;
static int index = 1;

public static void main(String[] args) {
    Scanner scan = new Scanner(System.in);
    int n = scan.nextInt();
    scan.close();
    String b = Integer.toBinaryString(n);
    char[] arr = b.toCharArray();
    System.out.println(arr);

    for (int i = 0; i < b.length(); i++) {
        if (arr[i] == index) {
            count++;
        } else {
            count = 0;
        }

        if (count > max) {
            max = count;
        }
    }

    System.out.println(max);
}

我总是得到0。看起来好像我的代码中的条件没有起作用。您能否就我在哪里做错了提供建议?


1
字符'1'转换为int后,其值并不是1,因此arr[i] == index永远不会成立。相反,您需要将index设置为一个具有值'1'的字符。 - azurefrog
2
建议:在调试器下逐步运行您的代码,并检查沿途的所有中间值。 - PM 77-1
谢谢 @azurefrog,我已经将索引的数据类型更改为 char。现在它可以正常工作了。 - Karthik
@Karthik 考虑现在删除你的问题。 - whatamidoingwithmylife
你需要 int 二进制还是 uint 二进制?例如,-1 的 int 二进制表示为全 1。 - Ctznkane525
5个回答

2

您的问题不是很清楚,但根据您的算法,我理解您正在尝试查找最常重复的1的数量。问题在于当您进行比较时if (arr[i] == index),比较是使用字符和整数进行的,因为arr的类型是字符数组。是吗?为了克服这个问题,您可以将char数组转换为整数,或将整数index值转换为char。我会这样做来克服这个问题。

if (arr[i] == index + '0')

这并不是一种非常优雅的解决方案。我假设你是一名学生,希望你展示出哪里有问题。如果我想���做类似于这样的事情,我会使用以下方法:

private static int maxConsecutiveOnes(int x) {
        // Initialize result
        int count = 0;

        // Count the number of iterations to
        // reach x = 0.
        while (x!=0) {
            // This operation reduces length
            // of every sequence of 1s by one.
            x = (x & (x << 1));

            count++;
        }

        return count;
}

我的技巧是,

      11101111   (x)
    & 11011110   (x << 1)
    ----------
      11001110   (x & (x << 1)) 
        ^    ^
        |    |
   trailing 1 removed

1
我喜欢这个用位(bit)的! - oleg.cherednik

1

将变量index的类型从int更改为char

static char index = 1;

以便在以下这行代码中进行比较:

if (arr[i] == index)

执行其工作。将int 1(在您的代码中,这是存储在index变量中的值)与char '1'(在您的示例中,它是当前检查的arr[]元素)进行比较,检查给定char的ASCII代码是否等于1的int值。这种比较永远不会为真,因为char '1'有一个ASCII代码49,这是正在与值1进行比较的值(49永远不等于1)。

您可能想要查看Web上的ASCII代码表,以查看所有字符都有分配对应的数字值。您需要知道,在使用==运算符比较charint时,这些值会被考虑在内。

当您将index的类型更改为char时,比较正常工作,您的代码似乎已经修复。


这个更改是否修复了整个程序?如果没有,那么这应该是一条注释。如果是的话,请在您的答案中更加明确,以便我可以为您点赞并让他们将您标记为正确答案。 - DavidS
1
@DavidS 谢谢你的建议。我试图改进我的答案,希望现在它符合你的要求。请过目一下。 - Przemysław Moskal
在这种情况下,这可能是Karthik最好的答案。她很可能是一位初学者程序员正在完成作业,因此我认为跳转到位运算(就像其他答案所做的那样)是不合适的。 - DavidS
@DavidS 我认为对于Karthik来说,这可能是最有帮助的答案,但我们也应该意识到,未来可能会有更有经验的用户寻找同一问题的更复杂或更高效的解决方案,因此我认为在这里放置更复杂的解决方案是一个好主意 :-) - Przemysław Moskal

1
我理解您的意思是,您想要计算一个整数值的二进制表示中连续的1的最大长度。例如,对于7917=0b1111011101101,结果将为4(我们有以下1的组:1、2、3、4)。 您可以使用位运算(并避免字符串转换)。您需要一个计数器(用于计算当前组中1的数量)和最大值max,记录所有这些数量的最大值。您只需要检查最低位是否为1,然后将值向右旋转,直到它变成0,就像getMaxConsecutiveSetBit1函数一样。

或者以非常简单的方式进行 - 将其转换为二进制字符串并计算其中1字符的数量,如getMaxConsecutiveSetBit2。还有一个计数器+最大值。不要忘记,在Java中,char在JVM级别上是一个int。因此,您在比较charint1时不会出现编译问题,但这是错误的。要检查字符是否为1,必须使用字符 - '1'

public static void main(String[] args) {
    try (Scanner scan = new Scanner(System.in)) {
        int val = scan.nextInt();
        System.out.println(Integer.toBinaryString(val));
        System.out.println(getMaxConsecutiveSetBit1(val));
        System.out.println(getMaxConsecutiveSetBit2(val));
    }
}

public static int getMaxConsecutiveSetBit1(int val) {
    int max = 0;
    int cur = 0;

    while (val != 0) {
        if ((val & 0x1) != 0)
            cur++;
        else {
            max = Math.max(max, cur);
            cur = 0;
        }

        val >>>= 1;
    }

    return Math.max(max, cur);
}

public static int getMaxConsecutiveSetBit2(int val) {
    int max = 0;
    int cur = 0;

    for (char ch : Integer.toBinaryString(val).toCharArray()) {
        if (ch == '1')
            cur++;
        else {
            max = Math.max(max, cur);
            cur = 0;
        }
    }

    return Math.max(max, cur);
}

我认为你误解了。他们写的是“连续的 1”。对于0b11011,答案是2,因为最多有两个连续的1。 - DavidS

0
使用您的for循环结构,稍微更改一些内容并添加一些其他有用的统计信息。我计算数字中1的总数,连续1的数量(1组),以及最大连续1的数量。此外,您的for循环是基于字符串长度而不是数组长度进行循环,这只是有点挑剔。以下是代码:
int count = 0;
int max = 0;
char index = '1';
int consecutiveOnePairs = 0;
int numberOfOnes = 0;

Scanner scan = new Scanner(System.in);
int n = scan.nextInt();
String b = Integer.toBinaryString(n);
char[] arr = b.toCharArray();
System.out.println(arr);

for (int i = 0; i < arr.length; i++) {
    if (arr[i] == index)
    {
        count++;
        numberOfOnes++;
    }

    if((i + 1 == arr.length && count > 1) || arr[i] != index)
    {
        if(count > 1)
            consecutiveOnePairs++;
        if (count > max)
            max = count;
        count = 0;
    }
}

System.out.println("Total Number of 1's in " + n + " is " + numberOfOnes);
System.out.println("Total Number of Consecutive 1's in " + n + " is " + consecutiveOnePairs);
System.out.println("Greatest Number of Consecutive 1's in " + n + " is " + max);
scan.close();

输出

13247
11001110111111
Total Number of 1's in 13247 is 11
Total Number of Consecutive 1's in 13247 is 3
Greatest Number of Consecutive 1's in 13247 is 6

511
111111111
Total Number of 1's in 511 is 9
Total Number of Consecutive 1's in 511 is 1
Greatest Number of Consecutive 1's in 511 is 9

887
1101110111
Total Number of 1's in 887 is 8
Total Number of Consecutive 1's in 887 is 3
Greatest Number of Consecutive 1's in 887 is 3

0
如果您使用Java 8,可以尝试以下代码片段:
 public int maxOneConsecutive(int x)
  {
    String intAsBinaryStr = Integer.toBinaryString(x);
    String[] split = intAsBinaryStr.split("0");
    return Arrays.stream(split)
        .filter(str -> !str.isEmpty())
        .map(String::length)
        .max(Comparator.comparingInt(a -> a)).orElse(0);
  }

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接