力扣--两数之和(Java)

两数之和问题解法

思路讲解

我这个思路核心是"淘汰数组中值大于 target 的元素",这基于一个优化假设:如果一个元素的值大于 target,那么它与另一个正数相加时,和可能会超过 target(尤其在元素非负的情况下)。因此,先过滤掉这些元素可以缩小搜索范围,减少不必要的比较。但需要注意,这个优化有局限性:

  • 淘汰值大于 target 的元素可能会导致遗漏有效解。因为如果数组元素可能为负,此优化可能不适用。
  • 为了确保正确性,在过滤后,我们使用双重循环在剩余元素中比较每对组合,寻找和为目标值的两个数。双重循环简单但效率较低,适用于数组较小或过滤后元素较少的情况。

算法步骤详细分解:

  1. 淘汰阶段 :遍历原数组,创建一个新列表存储值小于或等于 target 的元素及其原始索引(因为淘汰元素会丢失索引信息)。
  2. 比较阶段 :在过滤后的列表上,使用双重循环遍历所有元素对(确保索引不同),检查每对元素的和是否等于 target
  3. 返回结果:找到符合条件的两个元素后,立即返回它们的下标(假设只有一个有效答案)。
Java 代码实现

以下是完整的 Java 代码,实现了上述思路。代码包含详细注释以帮助理解。

java 复制代码
import java.util.ArrayList;
import java.util.List;

public class TwoSum {
    public int[] twoSum(int[] nums, int target) {
        // 步骤1: 淘汰值大于 target 的元素,存储剩余元素的索引和值
        List<ElementWithIndex> filteredList = new ArrayList<>();
        for (int i = 0; i < nums.length; i++) {
            if (nums[i] <= target) {
                // 只添加值 <= target 的元素,保留原始索引
                filteredList.add(new ElementWithIndex(nums[i], i));
            }
        }

        // 步骤2: 在过滤后的列表中,使用双重循环比较每对元素
        for (int i = 0; i < filteredList.size(); i++) {
            for (int j = i + 1; j < filteredList.size(); j++) {
                // 获取元素值
                int num1 = filteredList.get(i).value;
                int num2 = filteredList.get(j).value;
                // 检查两个元素和是否等于 target,且索引不同
                if (num1 + num2 == target) {
                    // 返回原始索引
                    return new int[]{filteredList.get(i).index, filteredList.get(j).index};
                }
            }
        }

        // 如果没有找到,抛出异常(但题目保证有且只有一个答案)
        throw new IllegalArgumentException("No two sum solution");
    }

    // 辅助类:存储元素值及其原始索引
    private static class ElementWithIndex {
        int value;
        int index;

        ElementWithIndex(int value, int index) {
            this.value = value;
            this.index = index;
        }
    }

    // 测试示例
    public static void main(String[] args) {
        TwoSum solution = new TwoSum();
        // 示例 1
        int[] nums1 = {2, 7, 11, 15};
        int target1 = 9;
        int[] result1 = solution.twoSum(nums1, target1);
        System.out.println("输出: [" + result1[0] + ", " + result1[1] + "]"); // 预期 [0, 1]

        // 示例 2
        int[] nums2 = {3, 2, 4};
        int target2 = 6;
        int[] result2 = solution.twoSum(nums2, target2);
        System.out.println("输出: [" + result2[0] + ", " + result2[1] + "]"); // 预期 [1, 2]

        // 示例 3
        int[] nums3 = {3, 3};
        int target3 = 6;
        int[] result3 = solution.twoSum(nums3, target3);
        System.out.println("输出: [" + result3[0] + ", " + result3[1] + "]"); // 预期 [0, 1]
    }
}
代码说明
  • 淘汰阶段 :使用一个 ArrayList 存储 ElementWithIndex 对象,每个对象包含元素值 value 和原始索引 index。只有值小于或等于 target 的元素被保留(即 nums[i] <= target)。
  • 比较阶段 :双重循环遍历过滤后的列表,检查每对元素和是否等于 target。内层循环从 i+1 开始,避免使用相同元素和重复比较。
  • 辅助类ElementWithIndex 用于存储值和索引,确保在过滤后仍能访问原始下标。
  • 测试main 方法包含了您提供的三个示例,验证代码正确性。

这个是我目前认为一个比较简单容易理解的方法(还未开始学习数据结构),如果有什么可以改进的地方欢迎·评论区补充~!

相关推荐
唐青枫8 分钟前
Java Optional 实战指南:优雅处理空值与链式转换
java
一起学开源10 分钟前
一文读懂 ReAct 范式:让 AI Agent 真正学会“思考+行动“
java·javascript·react.js·ecmascript·react·alibaba·智能体开发
逍遥德1 小时前
MQTT教程详解-04.SpringBoot集成MQTT(告别手动控制)
java·spring boot·物联网·中间件·iot·iotdb
语戚1 小时前
力扣 3161. 块放置查询:线段树解法(Java 实现)
java·算法·leetcode·面试·线段树·力扣·
我命由我123452 小时前
Android 开发问题:MlKitException: An internal error occurred during initialization.
android·java·java-ee·android jetpack·android-studio·androidx·android runtime
888CC++2 小时前
java 并发编程
java·开发语言·python
无风听海3 小时前
JSON Web Token(JWT)完全指南
java·前端·json
JAVA社区3 小时前
Java高级全套教程(十一)—— Kubernetes 超详细企业级实战详解
java·运维·微服务·容器·面试·kubernetes
8Qi84 小时前
LeetCode 23. 合并 K 个升序链表 —— 小顶堆(PriorityQueue)
数据结构·算法·leetcode·链表·
在繁华处5 小时前
Java从零到熟练(九):并发编程基础
java·开发语言