LeetCode 1 给定一个整数数组 nums 和一个目标值 target,请你在该数组中找出和为目标值的那 两个 整数,并返回他们的数组下标。

本文详细解析LeetCode经典题目“两数之和”的三种解法:暴力法、一遍哈希表及二遍哈希表。通过对比不同算法的时间与空间复杂度,帮助读者理解并掌握最优解决方案。

LeetCode 1

在这里插入图片描述

给定一个整数数组 nums 和一个目标值 target,请你在该数组中找出和为目标值的那 两个 整数,并返回他们的数组下标。

你可以假设每种输入只会对应一个答案。但是,你不能重复利用这个数组中同样的元素。

示例: 给定 nums = [2, 7, 11, 15], target = 9
因为 nums[0] + nums[1] = 2 + 7 = 9
所以返回 [0, 1]
01 暴力法
class Solution {
public int[] twoSum(int[] nums, int target) {
        for(int i = 0;i<nums.length;i++){
           for(int j = i+1; j<nums.length;j++){
              if(nums[i]+nums[j]==target){
              return new int[]{i,j};
         }
           }
        }
        throw new IllegalArgumentException("No two sum solution");
        }
        }

时间复杂度:O(n2) ;

空间复杂度:O(1)

02
一遍哈希表

class Solution {
    //一遍哈希表完成
    public int[] twoSum(int[] nums, int target) {
        Map<Integer, Integer> map = new HashMap<>();
        for(int i = 0;i<nums.length;i++){
            // map.put(nums[i],i);不能写在这里
            int complement = target - nums[i];
            if(map.containsKey(complement))
                return new int[] {map.get(complement),i};
            map.put(nums[i],i);//这个位置一定要注意
        }
        throw new IllegalArgumentException("No two sum solution");
    }
}

注意要点:测试用例如下,则有问题。所以说map.put(nums[i],i);的位置一定要注意,否则将会输出如下结构,这是错误的。

时间复杂度:O(n);

空间复杂度:O(n)(因为该哈希表中存放了n个元素)

03
二遍哈希表

class Solution {
    //二遍哈希表完成
    public int[] twoSum(int[] nums, int target) {
        Map<Integer, Integer> map = new HashMap<>();
        for(int i = 0;i<nums.length;i++){
            map.put(nums[i],i);
        }
        for(int i = 0;i<nums.length;i++){
            int complement = target-nums[i];
           //避免是同一个数,要做判断。

            if(map.containsKey(complement)&&map.get(complement)!=i){

                return new int[] {  i,map.get(complement) };
            }
        }
        throw new IllegalArgumentException("No two sum solution");
    }
}

注意要点:不要忘记做判断,可以参照方法2中的测试用例,你会发现当target为6的时候,当数组元素为3时,会两次返回该数组元素的下标,所以必须添加map.gets(complement)!=i这一行。此外,该方法一共迭代两次,第一次是将所有的数组元素及其下标放入哈希表中,第二次是检索哈希表。

时间复杂度:O(n);

空间复杂度:O(n)

<think>首先,用户的问题是基于引用内容,他们想在C++中实现一个功能:给定一个整数数组一个整数目标值找出数组目标值两个整数返回数组下标。引用中提供了C语言JavaScript的实现,但我需要给出C++版本。 关键点: - 输入:整数数组 nums整数 target - 输出:两个整数数组下标(例如 [i, j]) - 如果不能找到,返回空或其他指示(如 size=0) 从引用[1]中,有一个C语言的实现: - 它使用两个嵌套循环。 - 外层循环从0到numsSize-2(索引i),内层循环从i+1numsSize-1(索引j)。 - 如果 nums[i] + nums[j] == target,则返回下标 i j。 - 如果没有找到,返回0设置 *returnSize=0。 引用[2]提到,不需要重复检查元素,因为每个元素只需与后面的元素比较。 引用[3]是JavaScript实现,但逻辑类似:两个循环,跳过自身比较(j == i 时 continue)。 所以,我需要在C++中实现类似逻辑。C++中,输出通常通过引用参数或返回一个动态分配的数组来处理。 在LeetCode环境中,类似问题(如Two Sum)的处理方式是返回一个 vector<int>,包含两个下标。 用户指了“在C++中”,所以我应该使用C++标准库,如vector。 可能的实现: - 使用两个嵌套循环,时间复杂度 O(n^2),但对于小数组是可以的。 - 更高效的方法是用哈希表(unordered_map),时间复杂度 O(n)。 从引用[2],它暗示了更优化的方法:使用哈希映射来存储每个元素的索引,以便快速查找 target - x。 但在用户的问题中,他们提到“参考站内引用”,提供了三个引用,主要显示了暴力解法。所以,我应该先给出暴力解法,然后可能提到优化方法。 用户说:“我的思路是,肯要用两个for循环...”,所以暴力解法是合理的起点。 在C++中实现暴力解法: - 函数签名:类似引用[1],但用C++方式。 - 返回一个 vector<int> 包含两个下标。 - 如果没有找到,返回空 vector 或抛出异常;但在LeetCode风格中,通常会返回一个空 vector 或指返回大小。 标准做法:返回一个 vector<int>,如果找到,包含两个索引;否则,返回空(但通常保证有解)。 为了完整,我可以返回一个空 vector,或者根据输入处理。 现在,结构回答: - 系统级指令:使用 $...$ $$...$$ 格式数学表达式;用中文回答;生成相关问题;在引用段落末尾加引用标识。 - 用户可见层:结构清晰,真实可靠。 步骤: 1. 解释问题。 2. 给出C++实现代码。 3. 解释代码。 4. 生成相关问题。 使用引用标识:引用来自提供的上下文,所以我应该在相关部分加 [^1], [^2], [^3]。 例如: - 当引用暴力循环思想时,加 [^1]。 - 当提到优化时,加 [^2]。 代码示例: - 使用代码块,显示C++代码。 函数签名: - 输入:vector<int>& nums, int target - 输出:vector<int> 实现: ```cpp #include <vector> using namespace std; vector<int> twoSum(vector<int>& nums, int target) { for (int i = 0; i < nums.size(); ++i) { for (int j = i + 1; j < nums.size(); ++j) { if (nums[i] + nums[j] == target) { return {i, j}; // 返回包含 i j 的 vector } } } return {}; // 如果没有找到,返回空 vector } ``` 解释: - 嵌套循环:外层 i 从 0 到 size-1,内层 j 从 i+1 到 size-1,避免重复自身比较。 - 如果找到,返回 {i, j}。 - 否则,返回空 vector。 时间复杂度 O(n^2)。 更高效的方法:使用哈希表存储每个元素的值到索引的映射。 - 遍历数组,对于每个元素 nums[i],检查 target - nums[i] 是否在哈希表中。 - 如果在,返回两个下标。 - 否则,将 nums[i] i 添加到哈希表。 时间 O(n),空间 O(n)。 我可以先提供暴力解法,然后提到优化方法。 生成相关问题: - 类似于示例,3个问题。 - 例如: 1. 如何优化这个解决方案以减少时间复杂度? 2. 如果数组有重复元素,这个方法还能工作吗? 3. 这种方法在实际应用中的局限性是什么? 最后,在回答中自然地添加引用标识。 </think>以下是根据您的查询,针对在 C++ 中实现“找出整数数组目标值两个整数返回数组下标”的解决方案。我会逐步解释思路,提供代码示例。方案基于您提供的引用内容,主要采用暴力枚举法(时间复杂度 $O(n^2)$),参考了引用中的实现逻辑[^1][^2][^3]。 ### 问题分析与思路 给定一个整数数组 `nums` 一个目标值 `target`,目标是找到两个不同下标 $i$ $j$,使得 $nums[i] + nums[j] = target$。核心约束包括: - 每个元素只能使用一次。 - 元素不能与自己比较(即 $i \neq j$)。 - 如果找不到匹配,返回空结果。 从引用中可以看出,最直接的方法是使用两个嵌套循环遍历数组: - 外层循环遍历每个元素(下标 $i$)。 - 内层循环遍历 $i$ 之后的元素(下标 $j$),避免重复检查或自身比较,确保时间复杂度优化[^1][^2]。 - 时间复杂度为 $O(n^2)$,空间复杂度为 $O(1)$,适用于小规模数组;对于大规模数组,可优化为哈希表法(时间复杂度 $O(n)$)。 ### C++ 代码实现 下面是完整的 C++ 解决方案,使用标准库 `vector` 处理输入输出。代码基于暴力枚举法,确保符合 LeetCode 等平台的接口要求。 ```cpp #include <vector> using namespace std; vector<int> twoSum(vector<int>& nums, int target) { int n = nums.size(); // 获取数组长度 // 外层循环:遍历每个元素(下标 i 从 0 到 n-2) for (int i = 0; i < n - 1; ++i) { // 内层循环:遍历 i 之后的元素(下标 j 从 i+1 开始),避免重复检查[^1] for (int j = i + 1; j < n; ++j) { // 检查是否满足条件:nums[i] + nums[j] == target if (nums[i] + nums[j] == target) { return {i, j}; // 找到匹配,返回下标对 } } } return {}; // 未找到匹配,返回空 vector } ``` ### 代码说明 1. **输入与输出**: - **输入**:`vector<int>& nums`(整数数组的引用),`int target`(目标值)。 - **输出**:`vector<int>`,包含两个下标 $i$ $j$(顺序无关)。如果找不到,返回空 vector(`{}`)。 - **示例**:对于输入 `nums = [2, 7, 11, 15]`, `target = 9`,输出应为 `[0, 1]`,因为 $nums[0] + nums[1] = 2 + 7 = 9$[^3]。 2. **循环细节**: - 外层循环:$i$ 从 $0$ 到 $n-2$(通过 `i < n - 1` 确保 $j$ 存在),遍历每个元素。 - 内层循环:$j$ 从 $i+1$ 开始,避免 $j = i$ 导致自身比较,确保每个元素对只检查一次[^1][^2]。 - 条件检查:使用 `if (nums[i] + nums[j] == target)` 直接比较值。 3. **性能与可靠性**: - 时间复杂度为 $O(n^2)$,适用于小型数组(如 $n \leq 1000$)。 - 空间复杂度为 $O(1)$,无额外内存开销。 - 此方法在数组元素不重复时可靠;如果数组有重复元素,该方法仍能正确返回第一对匹配下标(但可能不是唯一解)。LeetCode 上的相关测试用例已验证其正确性[^3]。 4. **优化建议**: - 对于大规模数组,推荐使用哈希表(`unordered_map`)优化: - 时间复杂度 $O(n)$,空间复杂度 $O(n)$。 - 实现思路:遍历数组时存储每个元素的索引,对于每个 `nums[i]`,检查 `target - nums[i]` 是否在哈希表中[^2]。 - 示例代码片段(可替换上述嵌套循环): ```cpp #include <unordered_map> unordered_map<int, int> numMap; for (int i = 0; i < n; ++i) { int complement = target - nums[i]; if (numMap.find(complement) != numMap.end()) { return {numMap[complement], i}; } numMap[nums[i]] = i; // 存储元素值到下标 } return {}; ``` ### 相关问题 1. 如何优化这个解决方案以处理大规模数组(时间复杂度降至 $O(n)$)?[^2] 2. 如果数组中有重复元素,这个方法是否总能返回正确结果?如何修改代码以处理多个匹配对? 3. 在实际应用中,这种方法有哪些局限性?例如,对于内存受限环境如何处理? [^1]: 引用来源:用户提供的 C 语言实现,展示嵌套循环思路。 [^2]: 引用来源:LeetCode 官方解释,提到优化枚举方法。 [^3]: 引用来源:JavaScript 实现示例,验证输出正确性。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值