Как найти разность соседних элементов массива

Привет, Хабр!

Давайте поговорим про алгоритмы. Новички часто воспринимают их как что-то тяжёлое, сложное и непонятное, и отчасти это правда, но алгоритмы — это базис. А чем лучше вы знаете базис своей специальности, тем с большей вероятностью преуспеете в ней.

Сегодня мы посмотрим на одну красивую задачу по алгоритмам. Не будем отпугивать людей от работы с алгоритмами на самом старте, поэтому в нашем разборе не будет ни развесистых деревьев отрезков, ни разномастных оптимизаций задачи о рюкзаке, ни вероятностных тестов на простоту. User-friendly algos.

Вот задача: найти максимальную разницу между соседями.

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

Сложно? Можете попробовать сделать это до того, как нажмёте «Читать дальше», а потом проверим решение.

Итак, поехали. Максимальная разница между соседями.

Рассмотрим пример:
Пусть дан массив из N=11 элементов.

$A = [-1, -3, 10, 20, 21, 4, 3, 22, 10, -2, 15]$

Cначала решим задачу наивно, это часто помогает. Мы можем сделать именно то, что от нас требует условие задачи — отсортировать числа и найти разницу между соседними элементами. В зависимости от того, какую сортировку мы будем использовать, сложность решения будет варьироваться.

Если используем qsort или mergesort, то временная сложность составит

$O(N log N)$. Если нам известно, что числа распределены достаточно плотно на множестве целых чисел, то можно использовать сортировку подсчётом. Тогда мы получим

$O(U + N)$, где U — разность между максимальным и минимальным элементом. Случай относительно редкий, но стоит помнить про такую возможность.

После сортировки получим массив:

$As = [-3, -2, -1, 3, 4, 10, 10, 15, 20, 21, 22]$
Выпишем массив разностей:

$D = [1, 1, 4, 1, 6, 0, 5, 5, 1, 1]$
Получаем, что максимальная разница составляет 6.

Теперь подумаем, можно ли решить задачу быстрее? При переборе пар соседних элементов мы будем рассматривать много пар с маленькой разностью. Такие пары, возможно, и не смогут никогда дать наибольшую разность. И действительно, в отсортированном массиве у нас есть

$N-1$ пара соседних чисел, разность между максимумом и минимумом пусть равна

$U$. Тогда у наибольшей разности значение должно быть хотя бы

$U / (N - 1)$. Эта оценка верна по принципу Дирихле.

Если голуби рассажены в клетки, причём число голубей больше числа клеток, то хотя бы в одной из клеток находится более одного голубя.

9 клеток содержат 10 голубей, по принципу Дирихле, хотя бы в одной клетке находятся более одного голубя (Википедия)

Пусть

$D[1] = As[2]-As[1]$, …

$D[n - 1] = As[n] - As[n - 1]$,

$ As[i]$ — i-й элемент отсортированного массива. Тогда

$D[i] >= 0, D[1] + … + D[N-1] = U$.

Если предположить, что максимум из всех D[i] меньше

$U/(N-1)$, то вся сумма

$D[1] + … + D[N-1] $ будет строго меньше U — противоречие.

Отлично, мы получили нижнюю оценку на максимальную разность! Теперь попробуем как-то локализовать слишком близкие друг к другу элементы — разобьём отрезок от минимального до максимального элемента на полуинтервалы длиной

$L=U/(N-1)$. Каждый элемент попадёт ровно в один полуинтервал. Получим разбиение всех элементов на непересекающиеся группы, их ещё называют батчами.

Определить, в какой именно из них попал элемент x, очень просто — надо вычислить 1 + int((x — a_min) / L) (нумеруем с единицы), где a_min — минимальный элемент в массиве A, его можно найти за один проход по исходному массиву. Исключение составит только максимальный элемент — элементы с таким значением лучше сделать отдельным батчем.

На рисунке представлено распределение из описанного выше примера. Для ясности проделаем эту процедуру руками:

$U = 22 - (-3) = 25, N = 11 => L = 25/(11-1) = 2.5$

$A = [-1, -3, 10, 20, 21, 4, 3, 22, 10, -2, 15]$

$(-1 - (-3)) / 2.5 = 0.8 => batch = 1$

$(-3 - (-3)) / 2.5 = 0 => batch = 1$

$(10 - (-3)) / 2.5 = 13/2.5 = 5.2 =>batch = 6$

$(20 - (-3)) / 2.5 = 23/2.5 = 9.2 => batch = 10$

$(21 - (-3)) / 2.5 = 24/2.5 = 9.6 => batch = 10$

$(4 - (-3)) / 2.5 = 7/2.5 = 2.8 => batch = 3$

$(3 - (-3)) / 2.5 = 6/2.5 = 2.4 => batch = 3$

$(22 - (-3)) / 2.5 = 10 => batch = 11$

$(10 - (-3)) / 2.5 = 5.2 => batch = 6$

$(-2 - (-3)) / 2.5 = 0.4 => batch = 1$

$(15 - (-3)) / 2.5 = 7.2 => batch = 8$

Распределение по батчам выполняется за линейное время и требует

$O(n)$ дополнительной памяти. Обратите внимание, что элементы из одного батча не могут дать максимальную разницу между двумя элементами. Мы специально подобрали его размер таким образом.

Где могут находиться два соседних по значениям элемента? Конечно же, в соседних непустых батчах! Например, на рисунке элементы из третьего и шестого батча могут идти подряд в отсортированном массиве, так как батчи между ними пустые. Понятно, что соседними будут только два элемента — максимум из 3-го батча и минимум из 6-го. Аналогично, кандидатами на пару с максимальной разностью будут максимальный элемент первого батча и минимальный элемент третьего.

Выпишем все возможные пары элементов, которые могут дать наибольшую разность. Обозначим как min(i) — минимальный элемент в i-й группе, как max(i) — максимальный элемент.

max(1) = -1 min(3) = 3
max(3) = 4 min(6) = 10
max(6) = 10 min(8) = 15
max(8) = 15 min(10) = 20
max(10) = 21 min(11) = 22

Мы определили пары, которые стоит рассматривать. На практике необходимо сделать один проход по всем батчам, поддерживать последний непустой батч и максимальное значение в нём. Когда мы наткнёмся на следующий непустой батч, то найдём в нём минимум и попробуем обновить ответ.

Порадуемся — мы решили задачу за время

$O(N)$.

На самом деле, мы использовали достаточно известную идею и по сути проделали первые шаги карманной сортировки, в оригинале её называют bucket-sort.


Элементы раскладываются по корзинам, а потом элементы в каждой корзине сортируются

В худшем случае она работает за

$O(n^2)$, но среднее время работы при достаточном количестве батчей и равномерном распределении элементов составляет

$O(n)$.

«Но постойте, а как же случай, когда

$U=0$, почему вы не рассмотрели его?» — спросит внимательный читатель. Этот случай вырожденный, вот мы его и не рассмотрели, но давайте сделаем это сейчас для полноты вариантов.

Если разница между минимумом и максимумом равно нулю, то максимальная разница тоже равна нулю. Собственно, это всё.

Только зарегистрированные пользователи могут участвовать в опросе. Войдите, пожалуйста.

Быстро решили?


14.29%
Конечно, это же начальный уровень
12


5.95%
Решил, но своим способом (напишу в комментах)
5


1.19%
Можно ещё проще, сейчас покажу
1


65.48%
Даже не пытался, сразу пошёл смотреть ваше решение
55


10.71%
Не люблю алгоритмы
9

Проголосовали 84 пользователя.

Воздержались 27 пользователей.

We are given with an array. The array need not be sorted. The task is to find the maximum difference between adjacent elements of that array in its sorted form. So the first thing is to sort the array in increasing or decreasing order. Then we will iterate the array and calculate the adjacent difference of Arr[i+1]-Arr[i]. Then for each iteration we will compare this difference with the one which is found maximum so far.

Input − Arr[] = [ 1,5,10,2,7 ]

Output − Maximum adjacent difference in array in its sorted form is 3.

Explanation − Sorted Arr[] in increasing order = [ 1,2,5,7,10 ]. So the adjacent differences are as follows −

Arr[1]-Arr[0]=1, Maximum Difference=1
Arr[2]-Arr[1]=3, Maximum Difference=3
Arr[3]-Arr[2]=2, Maximum Difference=3
Arr[4]-Arr[3]=3, Maximum Difference=3

Input − Arr[] = [ 5,11,21,15,20 ]

Output − Maximum adjacent difference in array in its sorted form is 6.

Explanation − Sorted Arr[] in increasing order = [ 5,11,15,20,21 ]. So the adjacent differences are as follows −

Arr[1]-Arr[0]=6, Maximum Difference=6
Arr[2]-Arr[1]=4, Maximum Difference=6
Arr[3]-Arr[2]=5, Maximum Difference=6
Arr[4]-Arr[3]=1, Maximum Difference=6

Approach used in the below program is as follows

  • Input an integer array Arr[].

  • Sort the array in increasing order.( sorting order does not matter here )

  • Declare a variable say MaxD to store the maximum difference between adjacent elements found so far. Take its initial value as Arr[1]-Arr[0].

  • Start the loop, from the second element till last element index of array.

  • If the calculated difference between Arr[i+1]-Arr[i]>MaxD, update MaxD .

  • Continue this till we reach the second last element index.

  • Print the result MaxD as maximum adjacent element difference.

Example

#include <bits/stdc++.h>
using namespace std;
int max_adj_Diff(int A[],int size){
   int MaxD=A[1]-A[0];
   for(int i=1;i<size-1;i++){
      if(A[i+1]-A[i] > MaxD)
         MaxD=A[i+1]-A[i];
   }
   return MaxD;
}
int main(){
   int Arr[]={1,5,2,18,20,13};
   sort(Arr,6); //this is supposed to sort array in increasing order
   int md=max_adj_Diff(Arr,6);
   cout<<"Maximum adjacent difference in array in its sorted form :"<<md;
   return 0;
}

Output

If we run the above code it will generate the following output −

Maximum adjacent difference in array in its sorted form: 8

Максимальная смежная разница в массиве в отсортированном виде

30.12.2019Массивы, Поиск

Для данного массива найдите максимальную разницу между двумя последовательными элементами в его отсортированной форме.

Примеры:

Input : arr[] = {1, 10, 5}
Output : 5
Sorted array would be {1, 5, 10} and
maximum adjacent difference would be 
10 - 5 = 5

Input : arr[] = {2, 4, 8, 11}
Output : 4

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

Эффективное решение основано на идее сортировки по Голубой дыре . На самом деле мы не сортируем массив, нам просто нужно заполнить сегменты и отслеживать максимальное и минимальное значение каждого сегмента. Если бы мы нашли пустой сегмент, максимальный разрыв будет равен разнице максимального значения в предыдущем интервале — минимального значения в следующем интервале .

Ниже приведен код для вышеуказанного подхода.

C ++

#include <bits/stdc++.h>

using namespace std;

int maxSortedAdjacentDiff(int* arr, int n)

{

    int maxVal = arr[0], minVal = arr[0];

    for (int i = 1; i < n; i++) {

        maxVal = max(maxVal, arr[i]);

        minVal = min(minVal, arr[i]);

    }

    int maxBucket[n - 1];

    int minBucket[n - 1];

    fill_n(maxBucket, n - 1, INT_MIN);

    fill_n(minBucket, n - 1, INT_MAX);

    float delta = (float)(maxVal - minVal) / (float)(n - 1);

    for (int i = 0; i < n; i++) {

        if (arr[i] == maxVal || arr[i] == minVal)

            continue;

        int index = (float)(floor(arr[i] - minVal) / delta);

        if (maxBucket[index] == INT_MIN)

            maxBucket[index] = arr[i];

        else

            maxBucket[index] = max(maxBucket[index], arr[i]);

        if (minBucket[index] == INT_MAX)

            minBucket[index] = arr[i];

        else

            minBucket[index] = min(minBucket[index], arr[i]);

    }

    int prev_val = minVal;

    int max_gap = 0;

    for (int i = 0; i < n - 1; i++) {

        if (minBucket[i] == INT_MAX)

            continue;

        max_gap = max(max_gap, minBucket[i] - prev_val);

        prev_val = maxBucket[i];

    }

    max_gap = max(max_gap, maxVal - prev_val);

    return max_gap;

}

int main()

{

    int arr[] = { 1, 10, 5 };

    int n = sizeof(arr) / sizeof(arr[0]);

    cout << maxSortedAdjacentDiff(arr, n) << endl;

    return 0;

}

Джава

import java.util.Arrays;

class GFG {

    static int maxSortedAdjacentDiff(int[] arr, int n) {

        int maxVal = arr[0];

        int minVal = arr[0];

        for (int i = 1; i < n; i++) {

            maxVal = Math.max(maxVal, arr[i]);

            minVal = Math.min(minVal, arr[i]);

        }

        int maxBucket[] = new int[n - 1];

        int minBucket[] = new int[n - 1];

        Arrays.fill(maxBucket, 0, n - 1, Integer.MIN_VALUE);

        Arrays.fill(minBucket, 0, n - 1, Integer.MAX_VALUE);

        float delta = (float) (maxVal - minVal) / (float) (n - 1);

        for (int i = 0; i < n; i++) {

            if (arr[i] == maxVal || arr[i] == minVal) {

                continue;

            }

            int index = (int) (Math.round((arr[i] - minVal) / delta));

            if (maxBucket[index] == Integer.MIN_VALUE) {

                maxBucket[index] = arr[i];

            } else {

                maxBucket[index] = Math.max(maxBucket[index], arr[i]);

            }

            if (minBucket[index] == Integer.MAX_VALUE) {

                minBucket[index] = arr[i];

            } else {

                minBucket[index] = Math.min(minBucket[index], arr[i]);

            }

        }

        int prev_val = minVal;

        int max_gap = 0;

        for (int i = 0; i < n - 1; i++) {

            if (minBucket[i] == Integer.MAX_VALUE) {

                continue;

            }

            max_gap = Math.max(max_gap, minBucket[i] - prev_val);

            prev_val = maxBucket[i];

        }

        max_gap = Math.max(max_gap, maxVal - prev_val);

        return max_gap;

    }

    public static void main(String[] args) {

        int arr[] = {1, 10, 5};

        int n = arr.length;

        System.out.println(maxSortedAdjacentDiff(arr, n));

    }

  
}

python3

def maxSortedAdjacentDiff(arr, n): 

    maxVal, minVal = arr[0], arr[0

    for i in range(1, n): 

        maxVal = max(maxVal, arr[i]) 

        minVal = min(minVal, arr[i]) 

    maxBucket = [INT_MIN] * (n - 1

    minBucket = [INT_MAX] * (n - 1

    delta = (maxVal - minVal) // (n - 1

    for i in range(0, n):

        if arr[i] == maxVal or arr[i] == minVal: 

            continue

        index = (arr[i] - minVal) // delta 

        if maxBucket[index] == INT_MIN: 

            maxBucket[index] = arr[i] 

        else:

            maxBucket[index] = max(maxBucket[index],

                                             arr[i]) 

        if minBucket[index] == INT_MAX: 

            minBucket[index] = arr[i] 

        else:

            minBucket[index] = min(minBucket[index],

                                             arr[i]) 

    prev_val, max_gap = minVal, 0

    for i in range(0, n - 1): 

        if minBucket[i] == INT_MAX: 

            continue

        max_gap = max(max_gap, 

                      minBucket[i] - prev_val) 

        prev_val = maxBucket[i] 

    max_gap = max(max_gap, maxVal - prev_val) 

    return max_gap 

if __name__ == "__main__":

    arr = [1, 10, 5

    n = len(arr)

    INT_MIN, INT_MAX = float('-inf'), float('inf')

    print(maxSortedAdjacentDiff(arr, n))

C #

using System;

using System.Linq;

class GFG

{

static int maxSortedAdjacentDiff(int[] arr,     

                                 int n) 

{

    int maxVal = arr[0];

    int minVal = arr[0];

    for (int i = 1; i < n; i++)

    {

        maxVal = Math.Max(maxVal, arr[i]);

        minVal = Math.Min(minVal, arr[i]);

    }

    int []maxBucket = new int[n - 1];

    int []minBucket = new int[n - 1];

    maxBucket = maxBucket.Select(i => int.MinValue).ToArray(); 

    minBucket = minBucket.Select(i => int.MaxValue).ToArray();

    float delta = (float) (maxVal - minVal) / 

                  (float) (n - 1);

    for (int i = 0; i < n; i++) 

    {

        if (arr[i] == maxVal || arr[i] == minVal) 

        {

            continue;

        }

        int index = (int) (Math.Round((arr[i] - 

                             minVal) / delta));

        if (maxBucket[index] == int.MinValue)

        {

            maxBucket[index] = arr[i];

        

        else 

        {

            maxBucket[index] = Math.Max(maxBucket[index], 

                                                  arr[i]);

        }

        if (minBucket[index] == int.MaxValue)

        {

            minBucket[index] = arr[i];

        }

        else 

        {

            minBucket[index] = Math.Min(minBucket[index], 

                                                  arr[i]);

        }

    }

    int prev_val = minVal;

    int max_gap = 0;

    for (int i = 0; i < n - 1; i++)

    {

        if (minBucket[i] == int.MaxValue) 

        {

            continue;

        }

        max_gap = Math.Max(max_gap, minBucket[i] -

                                    prev_val);

        prev_val = maxBucket[i];

    }

    max_gap = Math.Max(max_gap, maxVal - 

                                prev_val);

    return max_gap;

}

public static void Main() 

{

    int []arr = {1, 10, 5};

    int n = arr.Length;

    Console.Write(maxSortedAdjacentDiff(arr, n));

}
}

Выход:

5

Временная сложность: O (n)
Вспомогательное пространство: O (n)

Рекомендуемые посты:

  • Максимальная длина подмассива с разницей между соседними элементами, равной 0 или 1
  • Вывести все тройки в отсортированный массив, которые образуют AP
  • Эффективный поиск в массиве, где разница между соседними составляет 1
  • Минимизировать сумму смежных разностей с удалением одного элемента из массива
  • Поиск элемента в массиве, где разница между соседними элементами равна 1
  • Минимальная абсолютная разница соседних элементов в круговой матрице
  • Максимальная битовая сумма в массиве без учета смежных элементов
  • Максимальная сумма в круговом массиве, так что нет двух соседних элементов
  • Симметричная разность двух отсортированных массивов
  • Переставить массив в максимально минимальной форме | Комплект 1
  • Максимум в массиве, который может сделать другой массив отсортированным
  • Переставить массив в максимально минимальной форме | Набор 2 (O (1) дополнительное пространство)
  • Максимальный элемент в отсортированном и повернутом массиве
  • Максимальное число, сформированное из массива с разрешенным количеством смежных свопов
  • Максимальная абсолютная разница в массиве

Максимальная смежная разница в массиве в отсортированном виде

0.00 (0%) 0 votes

Я как понял основная проблема это в алгоритме. Подкрашивать цифры я не умею ;_;

НО я могу предоставить логарифм :3 ВОТ :

int main()
{
    int massiw[] = {2,4,5,6,8,2,6,8,9,7,3,1};

    // вот алгоритм поиска двух ближайших чисел которые привели к самой большой разнице
    int datchik_t1 = 0;  int bigg_chislo = 0;// самая большая разница
     int chislo_1 = 0; // первое число давшее самую большую разницу
     int chislo_2 = 0; // второе число давшее самую большую разницу

    for(int i=0;i<(sizeof(massiw)/sizeof(int));i++){
        printf("  : %d n", i);
        datchik_t1 = massiw[i]-massiw[i+1];
        if(datchik_t1<0) // меняем знак на противоположный
            datchik_t1 = datchik_t1*(-1);
        if(datchik_t1>bigg_chislo){
            bigg_chislo = datchik_t1;  
            chislo_1 =i;  chislo_2 = i+1;
        }
    }

    printf(" самое большое число : %d n", bigg_chislo);
    printf(" два числа "преведших" к большому числу   : первое число - %d второе число - %d n", massiw [chislo_1], massiw [chislo_2]);
    printf(" места в массиве занимают :  %d и %d n", chislo_1+1, chislo_2+1); // плюс один чтоб перевести в "человеческие нормы" комп счититает с нуля 

    return 0;
}

введите сюда описание изображения

Вопрос от пользователя:

Дан массив целых чисел. Найти элемент, разность соседних элементов которого не меньше 72. Если таких элементов несколько, выбрать максимальный. Если таких элементов нет, выдать сообщение. Напиши программу которая будет использовать метод переупорядочивания списка с перестановкой найденного элемента в начало. Первоначально указатель q нулевой, указатель p указывает на начало списка; p перемещается на второй элемент, а q на первый. Указатель начала списка (table) перемещается на второй элемент, а указатель второго элемента на третий. Таким образом, второй элемент перемещается на первое место.. Программу написать на C++

Подождите!

Не закрывайте страницу. Нейросеть пишет ответ. Он появится тут.

Этот ответ написан нейросетью.

Искуственный интеллект во многом преуспевает, но в некоторых областях может давать неточные ответы.
Если вам не понравился ответ, попробуйте задать его более развёрнуто и конкретно, используя точные параметры.

Ответ нейросети:

Решение:

Для начала, создадим массив целых чисел и заполним его случайными числами:

++

#include <iostream>

#include <ctime>

#include <cstdlib>



#define N 10 // размер массива



using namespace std;



int main()

{

    int table[N];

    srand(time(0)); // инициализация генератора случайных чисел



    // заполнение массива случайными числами от 1 до 100

    for (int i = 0; i < N; i++) {

        table[i] = rand() % 100 + 1;

        cout << table[i] << " ";

    }

    cout << endl;



    return 0;

}

Далее, найдем элемент, удовлетворяющий условиям задачи:

++

// находим элемент, разность соседних элементов которого не меньше 72

int q = 0, p = 1, max = -1;

while (p < N) {

    if (table[p] - table[q] >= 72) {

        if (table[p] > max) {

            max = table[p];

        }

    }

    q++;

    p++;

}

if (max == -1) {

    cout << "Нет элементов, разность соседних которых не меньше 72";

    return 0;

}

cout << "Максимальный элемент: " << max << endl;

Затем, переупорядочим список с перестановкой найденного элемента в начало:

++

// переупорядочивание списка с перестановкой найденного элемента в начало

for (int i = 0; i < N; i++) {

    if (table[i] == max) { // найден максимальный элемент, переставляем его в начало

        for (int j = i; j > 0; j--) {

            swap(table[j], table[j-1]); // меняем элементы местами

        }

        break;

    }

}



// вывод полученного списка на экран

for (int i = 0; i < N; i++) {

    cout << table[i] << " ";

}

cout << endl;

Полный код программы:

++

#include <iostream>

#include <ctime>

#include <cstdlib>



#define N 10 // размер массива



using namespace std;



int main()

{

    int table[N];

    srand(time(0)); // инициализация генератора случайных чисел



    // заполнение массива случайными числами от 1 до 100

    for (int i = 0; i < N; i++) {

        table[i] = rand() % 100 + 1;

        cout << table[i] << " ";

    }

    cout << endl;



    // находим элемент, разность соседних элементов которого не меньше 72

    int q = 0, p = 1, max = -1;

    while (p < N) {

        if (table[p] - table[q] >= 72) {

            if (table[p] > max) {

                max = table[p];

            }

        }

        q++;

        p++;

    }

    if (max == -1) {

        cout << "Нет элементов, разность соседних которых не меньше 72";

        return 0;

    }

    cout << "Максимальный элемент: " << max << endl;



    // переупорядочивание списка с перестановкой найденного элемента в начало

    for (int i = 0; i < N; i++) {

        if (table[i] == max) { // найден максимальный элемент, переставляем его в начало

            for (int j = i; j > 0; j--) {

                swap(table[j], table[j-1]); // меняем элементы местами

            }

            break;

        }

    }



    // вывод полученного списка на экран

    for (int i = 0; i < N; i++) {

        cout << table[i] << " ";

    }

    cout << endl;



    return 0;

}

⚠️Зарепортить пост!

Чтобы оставить комментарий, необходимо авторизоваться.

Задай любой вопрос нейросети!

она справится с любой поставленной задачей быстрее чем поиск в Яндекс.

Для того, чтобы задать вопрос нейросети, необходимо войти на сайт.

Последние вопросы

(c) ChatGPT по русски 2023. Все права защищены. При обнаружении неправомерного контента пишите на [email protected]

Добавить комментарий