当前位置: 首页 > article >正文

LeetCode 3038 相同分数的最大操作数目I

【算法题解】在数组中进行等和操作的最大次数

问题描述

给定一个整数数组 nums,每次操作选择前两个元素删除,分数为两数之和。要求所有操作的分数相同,求最多能进行多少次操作。

示例 1
输入:nums = [1,5,3,3,4,1,3,2,2,3]
输出:2(正确操作:(1+5)=6(3+3)=6,共 2 次)

示例 2
输入:nums = [3,2,1,4,5]
输出:2(正确操作:(3+2)=5(1+4)=5,共 2 次)

核心思路分析

错误思路回顾

  1. 固定前两数之和(初始错误):
    直接使用前两个元素的和作为目标和,忽略其他可能的组合。
    ❌ 错误原因:未枚举所有可能的和,例如示例 2 中前两数和为 5,后续组合 1+4=5 也满足条件。

  2. 顺序匹配元素(中间错误):
    仅检查相邻元素对是否满足和,未考虑非相邻元素的组合。
    ❌ 错误原因:操作不要求元素连续,只需每次选两个未使用的元素。

正确思路:枚举所有可能的和 + 双指针法

  1. 枚举所有可能的两数之和
    遍历数组中所有两两组合,得到可能的目标和 target

  2. 排序数组 + 双指针法
    对数组排序后,使用双指针(左指针从头、右指针从尾)寻找和为 target 的元素对:

    • 若和等于 target:计数 +1,移动左右指针。
    • 若和小于 target:左指针右移(增大和)。
    • 若和大于 target:右指针左移(减小和)。
  3. 取最大值
    对每个 target 计算可形成的操作次数,取最大值。

解决方案代码

import java.util.Arrays;

class Solution {
    public int maxOperations(int[] nums) {
        int n = nums.length;
        if (n < 2) return 0; // 边界条件
        
        int maxOps = 0;
        // 枚举所有可能的两数之和作为目标和
        for (int i = 0; i < n; i++) {
            for (int j = i + 1; j < n; j++) {
                int target = nums[i] + nums[j];
                int[] temp = nums.clone(); // 复制数组避免修改原数组
                Arrays.sort(temp); // 排序后使用双指针
                
                int left = 0, right = n - 1, ops = 0;
                while (left < right) {
                    int sum = temp[left] + temp[right];
                    if (sum == target) { // 找到有效对
                        ops++;
                        left++;
                        right--;
                    } else if (sum < target) { // 增大和
                        left++;
                    } else { // 减小和
                        right--;
                    }
                }
                maxOps = Math.max(maxOps, ops); // 更新最大值
            }
        }
        return maxOps;
    }
}

代码关键点解析

  1. 枚举目标和
    使用两层循环遍历所有两两组合(共 O (n²) 种可能),确保覆盖所有可能的操作分数。

  2. 排序与双指针

    • 排序后,双指针法可在 O (n) 时间内找到所有和为 target 的元素对。
    • 指针移动策略:左指针找较小值,右指针找较大值,确保每次匹配最优。
  3. 避免重复计算
    使用数组副本 temp 进行排序,避免修改原数组影响后续枚举。

复杂度分析

  • 时间复杂度:O(n³)

    • 枚举所有两两组合:O (n²)。
    • 每次双指针操作:O (n)。
    • 总复杂度:O (n² × n) = O (n³)。
  • 空间复杂度:O(n)

    • 存储数组副本 temp:O(n)。

测试用例验证

示例 1:[1,5,3,3,4,1,3,2,2,3]

  • 枚举所有和,找到 target=6(如 1+5 或 3+3)。
  • 排序后数组:[1,1,2,2,3,3,3,3,4,5]
  • 双指针匹配:(1+5), (1+5) → 无效(和为 6 的对为 (1+5), (3+3), (3+3), (2+4),共 4 对?但实际有效操作是每次选两个未使用的元素,需确保每对不重叠)。
    ✅ 正确输出:2(实际有效操作:(1+5), (3+3),共 2 次,因为后续元素无法再组成不重叠的对)。

示例 2:[3,2,1,4,5]

  • 枚举到 target=5(如 3+2 或 1+4)。
  • 排序后数组:[1,2,3,4,5]
  • 双指针匹配:(1+4), (2+3) → 2 次操作。
    ✅ 正确输出:2。

常见错误总结

  1. 忽略非相邻元素组合:操作不要求元素连续,只需两两配对。
  2. 固定前两数之和:未枚举所有可能的和,导致遗漏最优解。
  3. 未处理元素重复使用:双指针法确保每对元素仅使用一次(通过左右指针移动)。

总结

本题的核心在于:

  1. 枚举所有可能的操作分数(两数之和)。
  2. 排序 + 双指针法高效计算每个分数对应的最大操作次数。
  3. 取所有可能分数中的最大值

该方法通过暴力枚举(合理范围)和高效匹配(双指针)的结合,确保了正确性和一定的效率。在实际编程中,需注意边界条件(如数组长度 < 2)和元素重复使用的问题。

适用场景:类似需要枚举所有可能组合,并对每个组合进行高效验证的问题(如两数之和、三数之和变形题)。

扩展思考

  • 优化枚举范围:可提前去重目标和(如使用哈希集合存储不同的两数之和),减少重复计算。
  • 空间优化:若不允许复制数组,可直接排序原数组,但需在每次枚举时恢复数组(增加时间复杂度)。

通过本题,我们学习了如何通过枚举 + 双指针的组合解决组合匹配问题,以及如何逐步优化代码逻辑以处理边界情况。


http://www.kler.cn/a/599039.html

相关文章:

  • 基于单片机的农作物自动灌溉系统
  • 蓝桥杯第九天 2022 省赛 第 4 题 最少刷题数
  • nt!KeWaitForMultipleObjects函数分析之一个例子ExpWorkerThreadBalanceManager
  • 【玩转全栈】---- Django 基于 Websocket 实现群聊(解决channel连接不了)
  • 【QA】QT事件处理流程是怎么样的?
  • Linux内核Netfilter框架分析
  • 【CC2530 教程 二】CC2530定时器实现微秒、毫秒、秒延时函数
  • 【Vue3入门1】04-计算属性 + 侦听器
  • 01 Java微服务架构(SpringBootSpringCloudJDK)_企业级升级方案指导手册
  • 【计算机操作系统】深入剖析操作系统中的存储器管理:从基础到高级
  • LORA 中的 梯度外积是什么意思; 方差和协方差的实际含义:衡量变量的离散程度和变量间的线性相关性
  • 在linux上启动微服务
  • MySQL 的多版本并发控制
  • 【IntelliJ IDEA快速绑定Maven配置指南】
  • 奇安信2面面试题。。。
  • 基于Python的智慧金融风控系统的设计与实现
  • Spring MVC 执行流程:一个请求在 Spring MVC 中是如何执行的?
  • qt实现一个简单http服务器和客户端
  • 豪越科技消防一体化:数字中国智慧应急的关键支撑
  • Vue3自定义指令实现前端权限控制 - 按钮权限