3834. Merge Adjacent Equal Elements

練習日期:2026-02-08

難度:Medium

類型:Array、Stack、Simulation、Weekly Contest 488

📘 題目敘述

給你一個整數陣列 nums

你必須重複進行以下合併操作,直到再也無法產生變化為止:

如果目前陣列中存在任意一對相鄰且相等的元素,請選擇最左邊的那一對相鄰元素,並把它們替換成一個新元素,新元素的值等於它們的總和。

每次合併後,陣列長度會減少 1。你要在更新後的陣列上持續重複操作,直到無法再合併。

請回傳所有可能的合併完成後的最終陣列。

條件限制

  • 1 <= nums.length <= 10^5
  • 1 <= nums[i] <= 10^5

🧠 解題思路

題目規則有一個很麻煩的地方:它強調每次一定要合併最左邊那一對相鄰相等元素。如果真的照規則每次去找最左邊相等對、合併一次、再重找一次,最壞會變成很多次掃描,容易超時。

我這份寫法的想法是:用一個「堆疊」來模擬合併後的結果,而且可以自然保證最左邊優先的效果。

我從左到右讀 nums,把結果維護在 st 裡,讓 st 代表目前已處理完的前綴,在完整合併規則下會變成什麼樣子。

當我拿到一個新數字 now(一開始就是 nums[i]),我只需要看 st 的最後一個元素:

  • 如果 st.back() != now,代表新元素放進去不會立刻產生相鄰相等,就直接 push 進 st
  • 如果 st.back() == now,代表形成了相鄰相等這一對,所以我就把 st.back() pop 掉,並把 now 變成 now * 2,然後再繼續檢查連鎖合併。

所以我用 while (!st.empty() && st.back() == now) 來處理連鎖合併,一次把所有會連鎖的合併做完,再把最後的 now 放回 st

最後整個 nums 掃完後,st 就是最終陣列。

所有變數

  • nums:題目輸入陣列
  • st:用來模擬合併結果的堆疊(我用 vector<long long> 當 stack)
  • now:目前正在處理、可能會一路翻倍合併的值

🪜 主要流程步驟

1. 用 st 維護目前處理到這裡的最終狀態

我建立一個 vector<long long> st,把它當作堆疊使用。st 裡存的就是目前已經處理完的前綴,經過題目規則完整合併後留下的序列。

2. 從左到右讀取每個元素,先把它當作 now

每讀到一個 nums[i],我把它放到 now(用 long long 是因為合併會變大)。

3. 只要 now 跟 st 最後一個元素相等,就代表會合併

如果 st.back() == now,就表示形成相鄰相等的一對,依規則要合併,所以先 st.pop_back(),再做 now *= 2。這一步做完後,新的 now 可能又和更前面的 st.back() 相等,所以要用 while 連鎖合併,直到不能合併為止。

4. 連鎖合併結束後,把最後的 now 放回 st

當 while 結束,代表 st 目前最後一個元素不等於 now(或 st 已空),此時把 now push 回 st

5. 全部處理完後回傳 st

當整個陣列都掃完,st 就是題目要求的最終陣列。

💻 程式碼實作

class Solution {
public:
    vector<long long> mergeAdjacent(vector<int>& nums) {
        vector<long long> st;
        for (int i : nums) {
            long long now = i;
            while (!st.empty() && st.back() == now) {
                st.pop_back();
                now *= 2;
            }
            st.push_back(now);
        }
        return st;
    }
};

https://leetcode.com/problems/merge-adjacent-equal-elements/

作者:scottnick
撰寫日期:2026-02-08
類別:
原文連結:https://scottnick.github.io/cpp-notes/all%20problems/3834-merge-adjacent-equal-elements.html