news 2026/6/7 7:26:30

2026-06-07:合并相邻且相等的元素。用go语言,给你一个整数数组 nums。你要反复做合并,直到再也找不到可以合并的相邻相等元素为止。 规则是:在当前数组里,只要存在某两个相邻位置上的值相同,

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
2026-06-07:合并相邻且相等的元素。用go语言,给你一个整数数组 nums。你要反复做合并,直到再也找不到可以合并的相邻相等元素为止。 规则是:在当前数组里,只要存在某两个相邻位置上的值相同,

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]
唯一一对相邻元素34不相等,没有可合并的元素,合并流程结束。


最终结果

合并完成后的数组:[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完整代码如下:

packagemainimport("fmt""unsafe")funcmergeAdjacent(nums[]int)[]int64{st:=nums[:0]// 原地for_,x:=rangenums{forlen(st)>0&&st[len(st)-1]==x{st=st[:len(st)-1]x*=2}st=append(st,x)}// 力扣的 int 就是 int64,直接 O(1) 转成 []int64return*(*[]int64)(unsafe.Pointer(&st))}funcmain(){nums:=[]int{3,1,1,2}result:=mergeAdjacent(nums)fmt.Println(result)}

Python完整代码如下:

# -*-coding:utf-8-*-fromtypingimportListdefmerge_adjacent(nums:List[int])->List[int]:""" 原地合并相邻的相同数字(类似 2048 游戏规则) 将相邻且相同的数字合并为它们的和(乘以2) """st=[]# 使用列表作为栈forxinnums:# 当栈不为空且栈顶元素等于当前元素时,进行合并whilestandst[-1]==x:st.pop()# 移除栈顶元素x*=2# 当前元素翻倍st.append(x)returnstdefmain():nums=[3,1,1,2]result=merge_adjacent(nums)print(result)if__name__=="__main__":main()

C++完整代码如下:

#include<iostream>#include<vector>#include<cstdint>usingnamespacestd;vector<int64_t>mergeAdjacent(vector<int>&nums){// 原地操作:使用 nums 的前部作为栈空间size_t stackSize=0;// 栈的大小for(intx:nums){// 当栈不为空且栈顶元素等于当前元素时,进行合并while(stackSize>0&&nums[stackSize-1]==x){stackSize--;// 弹出栈顶x*=2;// 当前元素翻倍}// 将当前元素放入栈中nums[stackSize]=x;stackSize++;}// 将结果转换为 int64_t 类型的 vectorvector<int64_t>result;result.reserve(stackSize);for(size_t i=0;i<stackSize;i++){result.push_back(nums[i]);}returnresult;}intmain(){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;return0;}

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/6/7 7:24:04

45_AI短片实战第十八弹:AIGC表情选择、画面裁切与音效分层——让成片“声”动起来

文章目录 一、表情选材:从两个版本中挑选最佳表演 1.1 问题描述 1.2 决策与操作 二、画面二次构图:16:9裁切与放大 2.1 问题与目的 2.2 操作步骤 三、音效设计:分层叠加与节奏匹配 3.1 音效库准备 3.2 音效分层策略 3.3 关键技巧:音效提前或延迟 四、碎石路面音效的持续感 …

作者头像 李华