Как я могу создать Java-программу для определения количества последовательных чисел в массиве?

#java #arrays #for-loop #if-statement

#java #массивы #for-цикл #if-оператор

Вопрос:

Я пытаюсь создать 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);
            
   
    }  
}
 

Комментарии:

1. Пожалуйста, прочитайте: Как отлаживать небольшие программы ( https://ericlippert.com/ ) . — Замечание: если мы пишем сообщение, в основе которого лежит исключение, мы всегда должны включать трассировку стека и выделять строки, вызывающие исключение.

2. Когда j == nums.length - 1 (что происходит, когда i == 0 ), то nums[j 1] выходит за рамки.

3. Хорошо, что вы ожидаете от массива чисел, например { 4, 3, 10, 11, 6, 1, 4, 8, 7 } Последовательности {10,11}, {3,4}, and {6,7,8} . Наибольший имеет размер 3 , но их сумма равна 7 . Итак, чего вы хотите?

Ответ №1:

Проблема исключения заключается в доступе nums[j 1] к . Обратите внимание, что j может быть таким же большим, как nums.length - 1 из-за цикла for . Таким образом, j 1 может быть числом.длина, которая является индексом массива 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 amp;amp; nums[j] - 1 == nums[j-1]) {
      j  ;
      counter  ;
    }
    i = j;
  }
}
System.out.print("Consective amount is"   counter);
 

Обратите внимание, что индекс i начинается с 1, поэтому мы можем быть уверены, что nums[i-1] существует.
Если nums имеет только один элемент, мы не должны сталкиваться с какими-либо проблемами, поскольку условие i < nums.length не будет выполнено. Мы считаем два последовательных элемента для каждого начала последовательности и один дополнительный элемент для каждого последующего последовательного (цикл while).
Когда последовательность заканчивается, мы пытаемся найти новую последовательность за ней, переместив индекс i в конец последней последовательности (j = i).

Приведенный выше код будет суммировать несколько различных последовательностей последовательных чисел. Например, массив [17,2,20,18,4,3] имеет пять последовательных чисел (2,3,4 и 17,18)

Алгоритм имеет временную кратность в пределах O (n), поскольку мы либо увеличиваем i, либо j по крайней мере на и пропускаем i до j после каждой последовательности.

Комментарии:

1. Если вы суммируете последовательности> 1, то { 4, 3, 10, 11, 6, 1, 4, 8, 7 } это {3,4},{10,11},{6,7,8} будет 7, а не 5.

2. @WJS вы правы. Мне не хватало некоторых скобок, цикл while должен запускаться только в том случае, если условие if истинно и найдено начало последовательности. Я исправил приведенный выше код.

Ответ №2:

Я бы рекомендовал пересмотреть ваш подход к сканированию по массиву. В идеале для решения этой проблемы вам должен потребоваться только один цикл for.

Я лично создал хэш-набор чисел, который не может содержать дубликатов. Оттуда вы можете выполнить итерацию от 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();
}
 

Комментарии:

1. Я не был уверен, чего хочет OP, поэтому я запустил ваш код. Как вы получаете 5 для { 4, 3, 10, 11, 6, 1, 4, 8, 7 }; Наибольшая последовательность имеет длину 3 . Но сумма всех последовательностей> 1 равна 7.

2. @WJS В этом массиве 5 последовательных чисел. 3, 4 и 6, 7, 8.

3. а как насчет 10 и 11? Там есть три группы последовательных чисел. Два, которые вы упомянули, и 10 и 11.

4. Хороший улов, изменил код, чтобы поймать самые большие числа.

5. Итак, OP хочет суммировать длины всех последовательностей длиной> 1? Это было непонятно мне из примера операции.

Ответ №3:

Вот еще один подход, при котором сортировка не требуется. Он использует BitSet . И, как и в вашем примере, is предполагает положительные числа ( 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();
 

Теперь выполните итерацию по набору битов, чтобы найти диапазон битов, которые занимают смежные позиции. Они будут представлять последовательные последовательности, сгенерированные при заполнении исходного набора битов. Отображаются только последовательности из двух или более.

 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);