【问题标题】:How can I create a java program to find the amount of consecutive numbers in an array?如何创建一个 java 程序来查找数组中连续数字的数量?
【发布时间】:2022-01-09 11:14:10
【问题描述】:

我正在尝试制作一个 Java 程序来查找数组中连续数字的数量。例如,如果一个数组具有值 1,8,10,4,2,3,则有 4 个连续的数字 (1,2,3,4)。我已经创建了这个程序,但是我在第 28 行和第 31 行遇到了 ArrayIndexOutOfBoundsException 的错误,我该如何解决这个错误? (如果错误得到修复,我什至不确定我制作的程序是否可以工作)。注意:我知道网上有很多解决方案,但我是初学者,我正在尝试以更简单的方式来做。

import java.util.Arrays;

class Main {
  public static void main(String[] args) {
    
    consec();
    

  }
    
    static void consec()
    {
            
      int[] nums = {16, 4, 5, 200, 6, 7, 70, 8};
      int counter=0;
      
      Arrays.sort(nums);
      for (int i=0; i < nums.length; i++)
        if (i != nums.length - 1)
          System.out.print(nums[i] + ", ");
        else
          System.out.print(nums[i]);

      for (int i=0; i < nums.length; i++)
        
        for (int j=i; j < nums.length - i; j++)
          if (nums[j + 1] - 1 == nums[j])
            counter++;
          
            else if (nums[j+1]==counter)
              System.out.print("Consective amount is" + counter);
            
   
    }  
}

【问题讨论】:

  • 请阅读:How to debug small programs (https://ericlippert.com/)。 --- 备注:如果我们写一篇文章的核心是异常,我们应该始终包含堆栈跟踪并突出显示抛出异常的行。
  • j == nums.length - 1i == 0 时发生),则nums[j + 1] 越界。
  • 好的,你对像{ 4, 3, 10, 11, 6, 1, 4, 8, 7 } 这样的数字数组有什么期望?序列是{10,11}, {3,4}, and {6,7,8}。最大的大小为3,但它们的总和为7。那你想要什么?

标签: java arrays for-loop if-statement


【解决方案1】:

异常的问题在于nums[j + 1] 的访问权限。 请注意,由于 for 循环,j 可以与 nums.length - 1 一样大。 因此 j + 1 可以是 nums.length ,它是一个 OutOfBounds 数组索引。

其次,我认为您的代码不能解决任务 - 例如,如果您计算的连续数字的数量出现在数组中,您只会打印结果。但是我不明白这些事情应该如何相关。 你可以这样解决问题:

for (int i = 1; i < nums.length; i++) {
  if (nums[i-1] == nums[i] - 1) {
    counter+= 2;
    int j = i + 1;
    while (j < nums.length && nums[j] - 1 == nums[j-1]) {
      j++;
      counter++;
    }
    i = j;
  }
}
System.out.print("Consective amount is" + counter);

注意索引 i 从 1 开始,因此我们可以确定 nums[i-1] 存在。 如果 nums 只有一个元素,我们不应该遇到任何问题,因为条件 i &lt; nums.length 不会被满足。我们为序列的每个开始计算两个结果,为每个后续结果(while 循环)计算一个添加元素。 当序列结束时,我们尝试通过将索引 i 移动到最后一个序列的末尾 (j = i) 来找到它后面的新序列。

上面的代码将对多个不同的连续数字序列求和。例如数组 [17,2,20,18,4,3] 有五个结果数(2,3,4 和 17,18)

该算法在 O(n) 内具有时间复杂性,因为我们将 i 或 j 至少增加 on 并在每个序列之后跳过 i 到 j。

【讨论】:

  • 如果你对序列求和 > 1,那么 { 4, 3, 10, 11, 6, 1, 4, 8, 7 }{3,4},{10,11},{6,7,8} 将是 7,而不是 5。
  • @WJS 你是对的。我遗漏了一些括号,只有当 if 条件为真并且找到序列的开头时,才应该开始 while 循环。我修复了上面的代码。
【解决方案2】:

我建议您重新考虑扫描阵列的方法。理想情况下,您应该只需要一个 for 循环来解决这个问题。

我个人创建了一个数字的 HashSet,它不能包含重复项。从那里,您可以从1 迭代到nums.length-1,并检查nums[i] - 1 == nums[i-1] 是否(即:它们是否连续)。如果它们相等,您可以将两个数字添加到 HashSet。

最后,你实际上得到了连续数字的集合,但是对于这个问题,你可以简单地返回集合的大小。

强烈建议您尝试此问题并按照我的说明进行操作。如果你只需要代码,这就是我想出的方法。

public static int countConsecutive(int[] nums) {
    Set<Integer> consecutive = new HashSet<>();

    if (nums.length <= 1)
        return 0;
    Arrays.sort(nums);

    for (int i = 1; i < nums.length; i++) {
        if (nums[i] != nums[i - 1] + 1)
            continue;
        consecutive.add(nums[i]);
        consecutive.add(nums[i - 1]);
    }
    return consecutive.size();
}

【讨论】:

  • 我不确定 OP 想要什么,所以我运行了你的代码。你如何得到5 for { 4, 3, 10, 11, 6, 1, 4, 8, 7 }; 最大序列的长度为3。但是所有序列 > 1 的总和是 7。
  • @WJS 该数组中有 5 个连续数字。 3、4 和 6、7、8。
  • 10 和 11 怎么样?那里有三组连续的数字。你提到的两个和 10 和 11。
  • 好捕获,修改代码以捕获最大数字。
  • 所以OP想要对所有长度> 1的序列的长度求和?从 OP 的示例中我不清楚。
【解决方案3】:

这是另一种不需要排序的方法。它使用BitSet。和你的例子一样,是假定正数(BitSet 不允许设置负数)。

int[] values = {4, 3, 10, 11, 6, 1, 4, 8, 7};

根据数值设置对应的位位置。

BitSet bits = new BitSet();
for (int i : values) {
    bits.set(i);
}

为输出、起始位位置和设置长度初始化一些值。

BitSet out = new BitSet();
int start = 0;
int len = bits.length();

现在遍历位集,找到占据相邻位置的位范围。这些将表示填充原始 BitSet 时生成的连续序列。仅显示两个或更多的序列。

while (start < len) {
    start = bits.nextSetBit(start);
    int end = bits.nextClearBit(start+1);
    if (start != end-1) {
        // populate the subset for output.
        out.set(start,end);
        System.out.println(out);
    }
    out.clear();
    start = end;
}

打印

{3, 4}
{6, 7, 8}
{10, 11}

如果您只想要最大的计数,而与实际值无关,那就更简单了。初始化位集后,只需使用它代替上面的即可。

int len = bits.length();
int total = 0;
while (start < len) {
    start = bits.nextSetBit(start);
    int end = bits.nextClearBit(start + 1);
    if (end - start > 1) {
        total += end - start;
    }
    start = end;
}
System.out.println(total);

【讨论】:

    猜你喜欢
    • 2021-10-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-12-18
    • 1970-01-01
    • 1970-01-01
    • 2016-04-27
    相关资源
    最近更新 更多