Учитывая массив целых чисел фиксированной длины arr, дублируйте каждое вхождение нуля, сдвигая остальные элементы вправо

#java #runtime-error #dsa

Вопрос:

Я написал этот код, он прошел начальные тестовые примеры, но при отправке он показывает ошибку во время выполнения. Я не могу понять, почему? Ошибка во время выполнения:- Массив индекса -1 выходит за рамки длины 8

 class Solution {
public int[] duplicateZeros(int[] arr) 
{
    int n=arr.length;
    int count=0;
    for(int i=0;i<n;i  )
    {
        if(arr[i]==0)
            count=count 1;
    }
    
    int loc= n-1;
    int p=n-1 count;
    if(count==0)
        return arr;
    for(int i=n-1,j=p;i>=0;i--,j--)
    {
        if(j<=n amp;amp; loc>=0)
        {
            if(arr[i]==0)
            {
                arr[loc]=0;
                arr[loc-1]=0;
                loc=loc-2;
            }
            else
            {
                arr[loc]=arr[i];
                loc=loc-1;
            }
        }
    }
    return arr;
 

}
}

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

1. Массив имеет фиксированную длину — когда вы сдвигаете элементы вправо, ожидается ли, что вы увеличите массив или сдвинутые элементы будут удалены из массива? Пожалуйста, добавьте входные данные для случаев успеха и неудачи.

Ответ №1:

В следующем коде if loc равно 0 и arr[i] равно 0, и j <= n вы вводите вложенные if и arr[loc-1] is arr[-1] , которые могут дать вам ArrayOutOfBoundException

 // If j <= n and loc is 0 enter the first if
if (j <= n amp;amp; loc >= 0) {
   // If arr[i] == 0 enter the second if
   if (arr[i] == 0) {
       arr[loc] = 0;
       arr[loc - 1] = 0;   // loc is 0 so arr[loc - 1] throw the Error
       loc = loc - 2;
   } ...
 

Ответ №2:

 class Solution {
    public int[] duplicateZeros(int[] arr) {
        int n = arr.length;
        int count = 0;
        /* While we are not at the end of arr and the value is 0... */
        for(; (count < n) amp;amp; (arr[count] == 0); count  ) {
            /* Add one to count until we are done */
        }
        
        /* If half or more of the array is 0, then we zero things and are done */
        if (count > n/2) {
            for (int i = count; i < n; i  ) {
                arr[i] = 0;
            }
            return arr;
        }

        /* We have shifting work to do :'( */
        int end = n - 1;
        int loc = n - 1 - count;
        int boundary = 2 * count;
        /* Shift from loc to end while we have not copied into a space that will be 0 */
        for(; end >= boundary; end--; loc--) {
            arr[end] = arr[loc];
        }
        
        /* Put a 0 into all the spots there should be a zero, ignoreing the places there is already a 0 */
        for (int i = count; i < boundary; i  ) {
            arr[i] = 0;
        }
        /* Done! */
        return arr;
    }
}
 

Я не проверял этот код… но это должно быть очень близко к тому, что вы хотите.
Я думаю, ваша проблема в том, что вы слишком усложнили свой код и попытались обернуть свои шаги в логику if{} else {}, в которой вам не было необходимости.

Вы также пытались выполнить цикл даффа, установив два 0 одновременно.

Кроме того, вам не нужно возвращать arr — когда вы вернетесь к функции caling, вы измените исходный массив.

Ответ №3:

Самая большая проблема заключается в том, что вы пытаетесь создать результат в том же массиве. Если есть какие-то 0, это не подойдет.

Вот немного более простое решение, требующее Java 8 или выше:

 public static int[] duplicateZeros(int[] arr) {
    return Arrays.stream(arr)
        .flatMap(i -> i == 0 ? IntStream.of(i, i) : IntStream.of(i))
        .toArray();
}