华为OD面试手撕真题 【合并相邻且相等的元素】多语言题解

题目描述

给你一个整数数组 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 <= 105
  • 1 <= nums[i] <= 105

题解

力扣原题链接

思路:栈模拟

  1. 题目要求:相邻两个元素相同情况下用它们和用和替代它们。并且新元素与左侧最近元素相等的话,会继续执行合并合并操作。
  2. 这种合并场景非常适合使用栈进行处理。处理逻辑如下:从前往后遍历数组,当前要插入的数为num = nums[i],进行如下处理
    • 判断num是否等于栈顶元素,如果执行合并操作,弹出栈顶元素, num = 2 * num(两个数的和)。递归循环执行此操作
    • num不能与左侧元素发生合并,插入栈顶结束。
  3. 通过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;
}
相关推荐
乌暮1 小时前
JVM 原理与实践:从运行时数据区到线上故障排查
java·开发语言·jvm·后端·学习·面试
时间的拾荒人2 小时前
Qt 界面布局与容器控件详解:从分组框到布局管理器
开发语言·qt·面试
ShineWinsu4 小时前
对于Redis:ZSet类型的解析
数据库·c++·redis·缓存·面试·有序集合·zset
keke.shengfengpolang5 小时前
2026年财务经营分析校招技术能力拆解:SQL取数、Power BI看板、AI辅助分析,面试到底考什么
面试
王中阳Go5 小时前
简历写「QPS 提升 3 倍」,面试官问「怎么压测的」,我卡在并发数怎么定
人工智能·后端·面试
浩腾数字多媒体7 小时前
如何选择性价比高的地面互动公司?
面试
YangYang9YangYan7 小时前
2027 秋招|大数据管理与应用 企业数字化岗位面试高频问题拆解与求职准备
面试·职场和发展
唠点键盘之外的16 小时前
15 微调 vs RAG:到底怎么选
人工智能·机器学习·面试·aigc
怕浪猫17 小时前
Prompt Engineering 面试怎么考?这 5 个范式你必须会
面试·程序员·github