Монотонният стек е стек, който поддържа своите елементи в напълно нарастващ или намаляващ ред. Това е ценен инструмент, когато се занимавате с проблеми, базирани на масиви, които изискват идентифициране на следващите по-големи или по-малки елементи. За нашия проблем — намиране на следващия по-голям елемент в масив — монотонният стек е ефективен подход, тъй като ни позволява да следим елементите по структуриран начин, помагайки бързо да идентифицираме следващия по-голям елемент. Сдвояването му с речник позволява бързо индексиране на елементи, оптимизирайки нашето решение.

Какъв е проблемът да питаш?

Дадени са два масива, nums1 (подмножество от nums2), трябва да намерим следващия по-голям елемент за всяко число в nums1 в nums2. Ако няма такъв по-голям елемент, ние го маркираме като -1. Просто казано, търсим първото число, което е по-голямо след всяко число от nums1 в масива nums2.

Приближаване:

Нашият подход за ефективно решаване на този проблем е използването на монотонен стек и речник. Ние използваме стека, за да следим числата, които са често срещани в nums1 и nums2, но все още не сме намерили следващото им по-голямо число в nums2. Речникът ни помага бързо да намерим индекса на всяко число в nums1, за да заменим отговора за това число бързо, след като намерим следващото му по-голямо число.

Ето как прилагаме това:

  • Инициализирайте масива с отговори с -1, тъй като -1 е стойността по подразбиране, ако не намерим следващия по-голям елемент за число.
  • Използвайте речниково разбиране, за да съпоставите всяко число с неговия индекс в nums1. Това ще ни помогне бързо да намерим позицията на число в nums1, когато трябва да актуализираме отговора му.
  • Инициализирайте празен стек. Този стек ще ни помогне да следим числата в nums2, които също са в nums1 и за които все още не сме намерили следващия по-голям елемент. Изваждаме число от стека само когато намерим следващото му по-голямо число.
  • Повторете над nums2. За всяко число:
  • Ако стекът не е празен и текущото число е по-голямо от върха на стека, извадете горната част на стека и актуализирайте отговора за това число в масива с отговори.
  • Ако текущото число е в nums1 (което можем да проверим с помощта на речника), избутайте го в стека.

Код на решението с обяснение ред по ред:

    # Initialize the answer array with -1's, as -1 is the default value if we don't find a next greater element
    ans = [-1] * len(nums1)
    # Map each number to its index in nums1 using enumerate, allowing us to quickly locate the position of a number in nums1
    dic = {num: i for i, num in enumerate(nums1)}
    # Initialize an empty stack, which will help us track numbers in nums2 that are also in nums1 and for which we have not yet found the next greater number
    stack = []
    # Iterate over nums2
    for i in range(len(nums2)):
        curr = nums2[i]
        # If the stack is not empty and the current number is greater than the top of the stack, 
        # this means we have found the next greater element for the num from nums1 on top of the stack
        # We pop this number from the stack and update the corresponding position in the answer array with the current number
        while stack and curr > stack[-1]:
            val = stack.pop()
            ans[dic[val]] = curr
        # If the current number exists in dic (indicating it is common between nums1 and nums2),
        # we add it to the stack for potential future comparison
        if curr in dic:
            stack.append(curr)
    return ans

Само код на решението:

    ans = [-1] * len(nums1)
    dic = {num: i for i, num in enumerate(nums1)}
    stack = []
    for i in range(len(nums2)):
        curr = nums2[i]
        while stack and curr > stack[-1]:
            val = stack.pop()
            ans[dic[val]] = curr
        if curr in dic:
            stack.append(curr)
    return ans

Анализ на сложността:

Времева сложност: O(n), където n е броят на елементите в nums2. Всеки елемент се посещава веднъж и в най-лошия случай се вмъква и премахва от стека веднъж, като и двете са O(1) операции.

Пространствена сложност: O(n), тъй като използваме стек и речник, който може да съдържа най-много n елемента.

Ако сте намерили тази статия за полезна, помислете да ме последвате за повече упътвания като тази. Не се колебайте да се свържете с нас, ако се борите с предизвикателство при програмирането, имате обратна връзка за статията или ако има конкретен проблем, с който искате да се справя следващия път.

Благодаря, че се свързахте и приятно кодиране! :)