2026-06-07:合并相邻且相等的元素。用go语言,给你一个整数数组 nums。你要反复做合并,直到再也找不到可以合并的相邻

举报
福大大架构师每日一题 发表于 2026/06/07 21:22:10 2026/06/07
【摘要】 2026-06-07:合并相邻且相等的元素。用go语言,给你一个整数数组 nums。你要反复做合并,直到再也找不到可以合并的相邻相等元素为止。规则是:在当前数组里,只要存在某两个相邻位置上的值相同,就可以进行合并。每次操作时,要优先挑选“最靠左”的那一对相邻相等元素,把这两个数用它们的和替换掉。完成一次合并后,数组长度会减少 1,然后继续在新数组上寻找相邻相等的最左那一对,重复此过程,直到无...
2026-06-07:合并相邻且相等的元素。用go语言,给你一个整数数组 nums。你要反复做合并,直到再也找不到可以合并的相邻相等元素为止。

规则是:在当前数组里,只要存在某两个相邻位置上的值相同,就可以进行合并。每次操作时,要优先挑选“最靠左”的那一对相邻相等元素,把这两个数用它们的和替换掉。完成一次合并后,数组长度会减少 1,然后继续在新数组上寻找相邻相等的最左那一对,重复此过程,直到无法再合并。

最终,返回合并完成后的数组。

1 <= nums.length <= 100000。

1 <= nums[i] <= 100000。

输入: nums = [3,1,1,2]。

输出: [3,4]。

解释:

中间的两个元素相等,将它们合并为 1 + 1 = 2,结果为 [3, 2, 2]。

最后的两个元素相等,将它们合并为 2 + 2 = 4,结果为 [3, 4]。

不再存在相邻且相等的元素。因此,答案为 [3, 4]。

题目来自力扣3834。

# 过程分步详解 

## 一、核心规则回顾
1. 每次必须找**当前数组中最靠左**的一对相邻相等元素合并;
2. 合并方式:两个相等数替换为它们的**和**(即数值×2),数组长度-1;
3. 合并后**重新遍历新数组**,继续找最左侧可合并对,直到无相邻相等元素为止。

---

## 二、完整执行过程(分步详细描述)
### 初始状态
原始数组:`[3, 1, 1, 2]`
长度:4
当前无任何合并操作,开始第一次查找。

---

### 第一步:查找并合并「最左侧相邻相等元素」
1. 从数组**左到右依次检查**相邻元素:
   - 第1个元素`3`和第2个元素`1`:不相等,跳过;
   - 第2个元素`1`和第3个元素`1`:**相等**,这是当前最左侧的可合并对。
2. 执行合并:两个`1`相加 = `2`,替换这两个元素;
3. 合并后新数组:`[3, 2, 2]`
   长度变为:3

---

### 第二步:在新数组中重新查找「最左侧相邻相等元素」
合并后必须**从头开始检查**新数组:
1. 从左到右依次检查:
   - 第1个元素`3`和第2个元素`2`:不相等,跳过;
   - 第2个元素`2`和第3个元素`2`:**相等**,这是当前最左侧的可合并对。
2. 执行合并:两个`2`相加 = `4`,替换这两个元素;
3. 合并后新数组:`[3, 4]`
   长度变为:2

---

### 第三步:最终检查(无可用合并)
检查最终数组 `[3, 4]`:
唯一一对相邻元素`3`和`4`不相等,**没有可合并的元素**,合并流程结束。

---

### 最终结果
合并完成后的数组:`[3, 4]`

---

## 三、代码实现的核心逻辑(文字描述)
代码用了**栈(切片模拟栈)**的高效思路,替代了「反复遍历数组」的低效方式,完美匹配题目规则:
1. 初始化一个空栈(复用原数组空间,不额外开辟大内存);
2. 遍历原始数组的每一个数字:
   - 把当前数字准备入栈;
   - **检查栈顶元素**:如果栈顶和当前数字相等,就弹出栈顶元素,当前数字翻倍(等价于合并);
   - 重复检查:直到栈顶和当前数字不相等,再把当前数字入栈;
3. 遍历结束后,栈中剩余的元素就是最终合并完成的数组。

这个逻辑**自动实现了「优先合并最左侧」**的规则,且无需反复遍历数组。

---

## 四、时间复杂度 & 额外空间复杂度
### 1. 总时间复杂度:**O(n)**
- `n` 是输入数组的长度;
- 每个元素**最多入栈1次、出栈1次**,没有嵌套循环,所有操作都是线性的;
- 即使数组长度达到上限 `10^5`,也能高效运行。

### 2. 总额外空间复杂度:**O(1)**
- 代码**复用了原数组的内存空间**(`st := nums[:0]`),没有创建新的大容量切片;
- 仅使用了几个临时变量(循环变量、栈长度等),占用空间是固定的,不随输入数组长度变化;
- 最终返回的数组也没有开辟新内存,是通过指针转换直接复用原空间,属于**原地操作**。

---

### 总结
1. 合并过程:先合并中间的`1+1=2`得到`[3,2,2]`,再合并`2+2=4`得到最终结果`[3,4]`;
2. 时间复杂度:**O(n)**(线性时间,高效处理十万级数据);
3. 额外空间复杂度:**O(1)**(原地操作,几乎不占用额外内存)。

# Go完整代码如下:

```go
package main

import (
"fmt"
"unsafe"
)

func mergeAdjacent(nums []int) []int64 {
st := nums[:0] // 原地
for _, x := range nums {
for len(st) > 0 && st[len(st)-1] == x {
st = st[:len(st)-1]
x *= 2
}
st = append(st, x)
}
// 力扣的 int 就是 int64,直接 O(1) 转成 []int64
return *(*[]int64)(unsafe.Pointer(&st))
}

func main() {
nums := []int{3, 1, 1, 2}
result := mergeAdjacent(nums)
fmt.Println(result)
}

```

![在这里插入图片描述](https://i-blog.csdnimg.cn/direct/cb9f62c0fa584884a1fb20a153c31117.png)

# Python完整代码如下:

```python
# -*-coding:utf-8-*-

from typing import List

def merge_adjacent(nums: List[int]) -> List[int]:
    """
    原地合并相邻的相同数字(类似 2048 游戏规则)
    将相邻且相同的数字合并为它们的和(乘以2)
    """
    st = []  # 使用列表作为栈
    
    for x in nums:
        # 当栈不为空且栈顶元素等于当前元素时,进行合并
        while st and st[-1] == x:
            st.pop()  # 移除栈顶元素
            x *= 2    # 当前元素翻倍
        st.append(x)
    
    return st

def main():
    nums = [3, 1, 1, 2]
    result = merge_adjacent(nums)
    print(result)

if __name__ == "__main__":
    main()
```

![在这里插入图片描述](https://i-blog.csdnimg.cn/direct/beb7571cff1f4eef8ad1b682f94e7c74.png)

# C++完整代码如下:

```cpp
#include <iostream>
#include <vector>
#include <cstdint>

using namespace std;

vector<int64_t> mergeAdjacent(vector<int>& nums) {
    // 原地操作:使用 nums 的前部作为栈空间
    size_t stackSize = 0;  // 栈的大小

    for (int x : nums) {
        // 当栈不为空且栈顶元素等于当前元素时,进行合并
        while (stackSize > 0 && nums[stackSize - 1] == x) {
            stackSize--;     // 弹出栈顶
            x *= 2;          // 当前元素翻倍
        }
        // 将当前元素放入栈中
        nums[stackSize] = x;
        stackSize++;
    }

    // 将结果转换为 int64_t 类型的 vector
    vector<int64_t> result;
    result.reserve(stackSize);
    for (size_t i = 0; i < stackSize; i++) {
        result.push_back(nums[i]);
    }

    return result;
}

int main() {
    vector<int> nums = {3, 1, 1, 2};
    vector<int64_t> result = mergeAdjacent(nums);

    cout << "[";
    for (size_t i = 0; i < result.size(); i++) {
        if (i > 0) cout << " ";
        cout << result[i];
    }
    cout << "]" << endl;

    return 0;
}

```

![在这里插入图片描述](https://i-blog.csdnimg.cn/direct/e78883dd3f4a46aba53e43e7d25c6fdb.png)

【声明】本内容来自华为云开发者社区博主,不代表华为云及华为云开发者社区的观点和立场。转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息,否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。