题目描述
给你一个整数数组 nums。
你需要 重复 执行以下合并操作,直到无法再进行任何更改:
- 如果数组中存在 两个相邻且相等的元素 ,选择当前数组中 最左侧 的这对相邻元素,并用它们的 和 替换它们。
每次合并操作后,数组的大小 减少 1。对更新后的数组重复此过程,直到无法再进行任何操作。
返回完成所有可能的合并操作后的最终数组。
示例1
输入: nums = 3,1,1,2
输出: 3,4
解释:
- 中间的两个元素相等,将它们合并为
1 + 1 = 2,结果为[3, 2, 2]。 - 最后的两个元素相等,将它们合并为
2 + 2 = 4,结果为[3, 4]。 - 不再存在相邻且相等的元素。因此,答案为
[3, 4]。
示例2
输入: nums = 2,2,4
输出: 8
解释:
- 前两个元素相等,将它们合并为
2 + 2 = 4,结果为[4, 4]。 - 前两个元素相等,将它们合并为
4 + 4 = 8,结果为[8]。
示例3
输入: nums = 3,7,5
输出: 3,7,5
解释:
数组中没有相邻且相等的元素,因此不执行任何操作。
提示:
1 <= nums.length <= 1051 <= nums[i] <= 105
题解
思路:栈模拟
- 题目要求:相邻两个元素相同情况下用它们和用和替代它们。并且新元素与左侧最近元素相等的话,会继续执行合并合并操作。
- 这种合并场景非常适合使用
栈进行处理。处理逻辑如下:从前往后遍历数组,当前要插入的数为num = nums[i],进行如下处理- 判断
num是否等于栈顶元素,如果执行合并操作,弹出栈顶元素, num = 2 * num(两个数的和)。递归循环执行此操作 num不能与左侧元素发生合并,插入栈顶结束。
- 判断
- 通过2的操作模拟,栈中保留元素 既为合并操作后保留的元素。将栈中元素弹出使用数组保存即可。
栈的特性是:先进后出,转换为数组保存注意进行顺序反转
c++
c++
class Solution {
public:
vector<long long> mergeAdjacent(vector<int>& nums) {
vector<long long> res;
stack<long long> stk;
int n = nums.size();
for (int i = 0; i < n; i++) {
// 当前要插入的值
long long num = nums[i];
// 递归合并
while (!stk.empty() && stk.top() == num) {
stk.pop();
num *= 2;
}
stk.push(num);
}
// 递归弹出栈中数组元素
while (!stk.empty()) {
res.push_back(stk.top());
stk.pop();
}
// 反转,保证正确顺序
reverse(res.begin(), res.end());
return res;
}
};
JAVA
JAVA
class Solution {
public List<Long> mergeAdjacent(int[] nums) {
// 使用数组模拟栈
long[] stk = new long[nums.length];
int top = 0;
for (int i = 0; i < nums.length; i++) {
// 当前要插入的值
long num = nums[i];
// 递归合并
while (top > 0 && stk[top - 1] == num) {
num *= 2;
top--;
}
stk[top++] = num;
}
// 递归弹出栈中数组元素
List<Long> res = new ArrayList();
for (int i = 0; i < top; i++) {
res.add(stk[i]);
}
return res;
}
}
Python
python
class Solution:
def mergeAdjacent(self, nums):
stk = []
for num in nums:
# 当前要插入的值
num = int(num)
# 递归合并
while stk and stk[-1] == num:
stk.pop()
num *= 2
stk.append(num)
# 递归弹出栈中数组元素
res = []
while stk:
res.append(stk.pop())
# 反转,保证正确顺序
res.reverse()
return res
JavaScript
js
/**
* @param {number[]} nums
* @return {number[]}
*/
var mergeAdjacent = function(nums) {
const stk = [];
for (let i = 0; i < nums.length; i++) {
// 当前要插入的值
let num = nums[i];
// 递归合并
while (stk.length > 0 && stk[stk.length - 1] === num) {
stk.pop();
num *= 2;
}
stk.push(num);
}
// 递归弹出栈中数组元素
const res = [];
while (stk.length > 0) {
res.push(stk.pop());
}
// 反转,保证正确顺序
res.reverse();
return res;
};
Go
go
func mergeAdjacent(nums []int) []int64 {
stk := make([]int64, 0, len(nums))
for _, x := range nums {
// 当前要插入的值
num := int64(x)
// 递归合并
for len(stk) > 0 && stk[len(stk)-1] == num {
stk = stk[:len(stk)-1]
num *= 2
}
stk = append(stk, num)
}
// 递归弹出栈中数组元素
res := make([]int64, 0, len(stk))
for len(stk) > 0 {
res = append(res, stk[len(stk)-1])
stk = stk[:len(stk)-1]
}
// 反转,保证正确顺序
for i, j := 0, len(res)-1; i < j; i, j = i+1, j-1 {
res[i], res[j] = res[j], res[i]
}
return res
}
C语言
cpp
/**
* Note: The returned array must be malloced, assume caller calls free().
*/
long long* mergeAdjacent(int* nums, int numsSize, int* returnSize) {
long long* stk = (long long*)malloc(sizeof(long long) * numsSize);
int top = 0;
for (int i = 0; i < numsSize; i++) {
// 当前要插入的值
long long num = nums[i];
// 递归合并
while (top > 0 && stk[top - 1] == num) {
top--;
num *= 2;
}
stk[top++] = num;
}
// 递归弹出栈中数组元素
long long* res = (long long*)malloc(sizeof(long long) * top);
int size = top;
for (int i = 0; i < size; i++) {
res[i] = stk[top - 1];
top--;
}
// 反转,保证正确顺序
for (int i = 0, j = size - 1; i < j; i++, j--) {
long long temp = res[i];
res[i] = res[j];
res[j] = temp;
}
free(stk);
*returnSize = size;
return res;
}