LeetCode 第一题: 两数之和

news2024/10/6 0:30:24

文章目录

  • 第一题: 两数之和
  • 题目描述
    • 示例
  • 解题思路
  • Go语言实现 - 一遍哈希表法
    • C++实现
    • 算法分析
  • 排序和双指针法
    • Go语言实现 - 排序和双指针法
    • C++
    • 算法分析
  • 暴力法
    • Go语言实现 - 暴力法
    • C++
    • 算法分析
  • 二分搜索法
    • Go语言实现 - 二分搜索法
    • C++
    • 算法分析

第一题: 两数之和

题目描述

给定一个整数数组 nums​ 和一个目标值 target​,请你在该数组中找出和为目标值的那两个整数,并返回他们的数组索引。
你可以假设每种输入只会对应一个答案。但是,你不能重复利用这个数组中同样的元素。

示例

给定 nums = [2, 7, 11, 15], target = 9
因为 nums[0] + nums[1] = 2 + 7 = 9
所以返回 [0, 1]

解题思路

  1. 暴力法:双重循环遍历数组中的每个数,寻找是否存在一个数与它相加等于目标值。
  2. 两遍哈希表法:遍历数组,将每个数及其索引存入哈希表,然后再次遍历数组,查找 target - nums[i]​​ 是否在哈希表中。
  3. 一遍哈希表法:遍历数组,对于每个数,查找 target - nums[i]​​ 是否在哈希表中,如果在,直接返回结果;如果不在,将当前数存入哈希表。

截图为Go语言的测试

Go语言实现 - 一遍哈希表法

package main
func twoSum(nums []int, target int) []int {
    hashTable := make(map[int]int)
    for i, num := range nums {
        complement := target - num
        if index, ok := hashTable[complement]; ok {
            return []int{index, i}
        }
        hashTable[num] = i
    }
    return nil
}

C++实现

#include <vector>
#include <unordered_map>

class Solution {
public:
    std::vector<int> twoSum(std::vector<int>& nums, int target) {
        std::unordered_map<int, int> hashTable;
        for (int i = 0; i < nums.size(); ++i) {
            int complement = target - nums[i];
            if (hashTable.find(complement) != hashTable.end()) {
                return {hashTable[complement], i};
            }
            hashTable[nums[i]] = i;
        }
        return {};
    }
};

算法分析

  • 时间复杂度:O(n),其中 n 是数组中的元素数量。我们只遍历了包含有 n 个元素的列表两次。在哈希表中的操作时间复杂度为 O(1)。
  • 空间复杂度:O(n),所需的额外空间取决于哈希表中存储的元素数量,该表中存储了 n 个元素。
    这个Go语言实现的代码简单易懂,效率较高,适合解决这类问题。

image

排序和双指针法

  1. 首先,创建一个数组,包含原始数组的元素和它们的索引。

  2. 然后,根据数组元素对数组进行排序。

  3. 使用两个指针,一个从开始(最小元素)的位置,另一个从结束(最大元素)的位置。

  4. 比较两个指针指向的元素之和与目标和:

    • 如果和等于目标和,返回两个元素的索引。
    • 如果和小于目标和,移动左侧指针,使它指向一个更大的数。
    • 如果和大于目标和,移动右侧指针,使它指向一个更小的数。
      这种方法的关键在于,排序后我们可以使用双指针高效地找到两个数,使得它们的和等于目标和。

Go语言实现 - 排序和双指针法

package main
import (
	"sort"
)
type Pair struct {
	Value int
	Index int
}
func twoSum(nums []int, target int) []int {
	pairs := make([]Pair, len(nums))
	for i, num := range nums {
		pairs[i] = Pair{Value: num, Index: i}
	}
	sort.Slice(pairs, func(i, j int) bool {
		return pairs[i].Value < pairs[j].Value
	})
	left, right := 0, len(nums)-1
	for left < right {
		sum := pairs[left].Value + pairs[right].Value
		if sum == target {
			return []int{pairs[left].Index, pairs[right].Index}
		} else if sum < target {
			left++
		} else {
			right--
		}
	}
	return nil
}

C++

#include <vector>
#include <algorithm>
#include <utility>

class Solution {
public:
    std::vector<int> twoSum(std::vector<int>& nums, int target) {
        std::vector<std::pair<int, int>> numWithIndex;
        for (int i = 0; i < nums.size(); ++i) {
            numWithIndex.push_back({nums[i], i});
        }
        std::sort(numWithIndex.begin(), numWithIndex.end());

        int left = 0, right = nums.size() - 1;
        while (left < right) {
            int sum = numWithIndex[left].first + numWithIndex[right].first;
            if (sum == target) {
                return {numWithIndex[left].second, numWithIndex[right].second};
            } else if (sum < target) {
                ++left;
            } else {
                --right;
            }
        }
        return {};
    }
};

算法分析

  • 时间复杂度:O(nlogn),其中 n 是数组中的元素数量。排序的时间复杂度是 O(nlogn),双指针遍历的时间复杂度是 O(n)。
  • 空间复杂度:O(n),我们需要一个额外的数组来存储元素和它们的索引。
    这种方法在空间复杂度上与哈希表方法相同,但时间复杂度稍高,因为它需要排序。然而,这种方法在不允许修改原数组或需要保持元素原始顺序的情况下可能更有用。

image

暴力法

  1. 使用两个嵌套循环遍历数组中的所有元素对。
  2. 对于每一对元素,检查它们的和是否等于目标和。
  3. 如果找到一对元素的和等于目标和,返回这两个元素的索引。
    这种方法的时间复杂度是 O(n^2),因为它需要对数组中的每一对元素进行一次检查。

Go语言实现 - 暴力法

package main
func twoSum(nums []int, target int) []int {
    for i := 0; i < len(nums); i++ {
        for j := i + 1; j < len(nums); j++ {
            if nums[i] + nums[j] == target {
                return []int{i, j}
            }
        }
    }
    return nil
}

C++

#include <vector>

class Solution {
public:
    std::vector<int> twoSum(std::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};
                }
            }
        }
        return {};
    }
};

算法分析

  • 时间复杂度:O(n^2),其中 n 是数组中的元素数量。最坏的情况下,我们需要遍历每个元素与其他元素的组合。
  • 空间复杂度:O(1),我们只需要常数级别的额外空间来存储索引。
    暴力法是一种简单直接的方法,但是对于大型数据集来说,它的效率不高。在实际应用中,通常会优先考虑使用哈希表或排序和双指针法来解决这类问题。

image

二分搜索法

  1. 首先,对数组进行排序,并创建一个新数组来保存排序后元素的原始索引。
  2. 对于数组中的每个元素,使用二分搜索查找 target - nums[i]​。
  3. 如果找到,确保两个元素的原始索引不同,然后返回它们的原始索引。
    这种方法的关键在于,排序后我们可以使用二分搜索高效地找到第二个数。

Go语言实现 - 二分搜索法

package main
import (
	"sort"
)
func twoSum(nums []int, target int) []int {
	indexes := make([]int, len(nums))
	for i := range nums {
		indexes[i] = i
	}
	sort.Slice(indexes, func(i, j int) bool {
		return nums[indexes[i]] < nums[indexes[j]]
	})
	for i := 0; i < len(nums); i++ {
		left, right := i+1, len(nums)-1
		complement := target - nums[indexes[i]]
		for left <= right {
			mid := left + (right-left)/2
			if nums[indexes[mid]] == complement {
				return []int{indexes[i], indexes[mid]}
			} else if nums[indexes[mid]] < complement {
				left = mid + 1
			} else {
				right = mid - 1
			}
		}
	}
	return nil
}

C++

#include <vector>
#include <algorithm>
#include <numeric>

class Solution {
public:
    std::vector<int> twoSum(std::vector<int>& nums, int target) {
        std::vector<int> indexes(nums.size());
        std::iota(indexes.begin(), indexes.end(), 0);
        std::sort(indexes.begin(), indexes.end(), [&nums](int i, int j) { return nums[i] < nums[j]; });

        for (int i = 0; i < nums.size(); ++i) {
            int left = i + 1, right = nums.size() - 1;
            int complement = target - nums[indexes[i]];
            while (left <= right) {
                int mid = left + (right - left) / 2;
                if (nums[indexes[mid]] == complement) {
                    return {indexes[i], indexes[mid]};
                } else if (nums[indexes[mid]] < complement) {
                    left = mid + 1;
                } else {
                    right = mid - 1;
                }
            }
        }
        return {};
    }
};

算法分析

  • 时间复杂度:O(nlogn),其中 n 是数组中的元素数量。排序的时间复杂度是 O(nlogn),二分搜索的时间复杂度是 O(logn),总共进行了 n 次二分搜索。
  • 空间复杂度:O(n),我们需要一个额外的数组来保存索引。
    二分搜索法在空间复杂度上与哈希表方法相同,但时间复杂度稍高,因为它需要排序。这种方法在不允许修改原数组或需要保持元素原始顺序的情况下可能更有用。然而,对于"两数之和"这个问题,哈希表法通常是更优的选择,因为它的时间复杂度更低。

image

C++的实现

image

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1469511.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【统计分析数学模型】聚类分析: 系统聚类法

【统计分析数学模型】聚类分析&#xff1a; 系统聚类法 一、聚类分析1. 基本原理2. 距离的度量&#xff08;1&#xff09;变量的测量尺度&#xff08;2&#xff09;距离&#xff08;3&#xff09;R语言计算距离 三、聚类方法1. 系统聚类法2. K均值法 三、示例1. Q型聚类&#x…

变量与数据类型(详解版)

新年的第一篇博客&#xff0c;我也开始步入了对于java的学习&#xff0c;感觉c语言还是有很多的不懂&#xff0c;还是会继续学习c语言的&#xff0c;毕竟还是练习太少了&#xff01; 话不多说&#xff0c;我们直接开整&#xff01; 1. 字面常量 如上图中的输出语句&#xff0…

(202402)多智能体MetaGPT入门1:MetaGPT环境配置

文章目录 前言拉取MetaGPT仓库1 仅仅安装最新版2 拉取源码本地安装MetaGPT安装成果全流程展示 尝试简单使用1 本地部署大模型尝试&#xff08;失败&#xff09;2 讯飞星火API调用 前言 感谢datawhale组织开源的多智能体学习内容&#xff0c;飞书文档地址在https://deepwisdom.…

Java内部类的使用与应用

内部类的使用与应用 1. 内部类用法 普通内部类&#xff1a; 实例化内部类对象需要先实例化外部类对象&#xff0c;然后再通过OuterClassName.new InnerClassName()方式实例化内部类。内部类对象在创建后会与外部类对象秘密链接&#xff0c;因此无法独立于外部类创建内部类对象…

智慧农业—农业资源数据中心

综述 农业资源数据中心建设的目标是将大量的农业生产信息通过采集、清洗、核准后实现统一存储、统一管理,实现数据的共享和集中管理,保障数据的安全,也为数据的挖掘分析提供决策分析创造条件。 农业资源数据中心的数据架构如下图所示: (1)农业专家数据库。主要收录国内、…

手撕Transformer(二)| Transformer掩码机制的两个功能,三个位置的解析及其代码

文章目录 1 掩码的两个功能1.1 功能1 输入掩码&#xff0c;统一长度1.2 功能2 遮挡未预测信息 2 掩码存在的三个位置3 代码实现 Transformer的掩码机制是非常重要的 三个位置&#xff0c;两个功能 1 掩码的两个功能 1.1 功能1 输入掩码&#xff0c;统一长度 实现不同的长度句…

使用C++和SFML库创建2D游戏

FML&#xff08;Simple and Fast Multimedia Library&#xff09;是一个跨平台的C库&#xff0c;用于开发2D游戏和多媒体应用程序。它提供了许多功能&#xff0c;包括图形、声音、网络、窗口管理和事件处理等。 ———————————————不怎么完美的分割线——————…

使用命令符用cd切换不了

bug:cd 切换不进去 解决办法&#xff1a; 在cd后面加 /d

(HAL)STM32F103C6T8——软件模拟I2C驱动0.96寸OLED屏幕

一、电路接法 电路接法参照江科大视频。 二、相关代码及文件 说明&#xff1a;代码采用hal库&#xff0c;通过修改江科大代码实现。仅OLED.c文件关于引脚定义作了hal库修改&#xff0c;并将宏定义OLED_W_SCL(x)、OLED_W_SDA(x)作了相关修改。 1、OLED.c void OLED_I2C_Init(voi…

32单片机基础:旋转编码器计次

接线图如上图所示。 我们初始化一下PB0和PB1两个GPIO口外设中断&#xff0c;当然&#xff0c;这里只初始化一个外部中断也能完成功能的对于编码器而言&#xff0c;下图所示为正转的波形。如果把一相的下降沿用作触发中断&#xff0c;在中断时刻读取另一相的电平&#xff0c;正…

普中51单片机学习(红外通信)

红外通信 红外线系统的组成 外线遥控器已被广泛使用在各种类型的家电产品上&#xff0c;它的出现给使用电器提供了很多的便利。红外线系统一般由红外发射装置和红外接收设备两大部分组成。红外发射装置又可由键盘电路、红外编码芯片、电源和红外发射电路组成。红外接收设备可由…

Spring Boot中的@Scheduled注解:定时任务的原理与实现

1. 前言 本文将详细探讨Spring Boot中Scheduled注解的使用&#xff0c;包括其原理、实现流程、步骤和代码示例。通过本文&#xff0c;读者将能够了解如何在Spring Boot应用中轻松创建和管理定时任务。 2. Scheduled注解简介 在Spring框架中&#xff0c;Scheduled注解用于标记…

面试经典150题【21-30】

文章目录 面试经典150题【21-30】6.Z字形变换28.找出字符串中第一个匹配项的下标68.文本左右对齐392.判断子序列167.两数之和11.盛最多水的容器15.三数之和209.长度最小的子数组3.无重复字符的最长子串30.串联所有单词的子串 面试经典150题【21-30】 6.Z字形变换 对于“LEETC…

五种多目标优化算法(MOBA、NSWOA、MOJS、MOAHA、MOPSO)性能对比(提供MATLAB代码)

一、5种多目标优化算法简介 多目标优化算法是用于解决具有多个目标函数的优化问题的一类算法。其求解流程通常包括以下几个步骤: 1. 定义问题:首先需要明确问题的目标函数和约束条件。多目标优化问题通常涉及多个目标函数,这些目标函数可能存在冲突,需要在不同目标之间进…

udp服务器【Linux网络编程】

目录 一、UDP服务器 1、创建套接字 2、绑定套接字 3、运行 1&#xff09;读取数据 2&#xff09;发送数据 二、UDP客户端 创建套接字&#xff1a; 客户端不用手动bind 收发数据 处理消息和网络通信解耦 三、应用场景 1、服务端执行命令 2、Windows上的客户端 3…

DiceCTF 2024 -- pwn

baby-talk 题目给了 Dockerfile&#xff0c;但由于笔者 docker 环境存在问题启动不起来&#xff0c;所以这里用虚拟机环境做了&#xff08;没错&#xff0c;由于不知道远程 glibc 版本&#xff0c;所以笔者远程也没打通&#xff09;笔者本地环境为 glibc 2.31-0ubuntu9.9。然后…

Shell grep命令练习题

目录 1含有“48“字符串的行的总数 2显示含有“48“字符串的所有行的行号 3精确匹配只含有“48”字符串的行 4抽取代码为484和483的城市位置 5显示使行首不是4或8 6显示含有九月份(Sept)的行 7显示以K开头&#xff0c;以D结尾的所有代码 8显示头两个是大写字母&#xff0c;中间…

规则持久化(Sentinel)

规则持久化 基于Nacos配置中心实现推送 引入依赖 <dependency><groupId>com.alibaba.csp</groupId><artifactId>sentinel-datasource-nacos</artifactId> </dependency> 流控配置文件 [{"resource":"/order/flow",…

《Docker 简易速速上手小册》第6章 Docker 网络与安全(2024 最新版)

文章目录 6.1 Docker 网络概念6.1.1 重点基础知识6.1.2 重点案例&#xff1a;基于 Flask 的微服务6.1.3 拓展案例 1&#xff1a;容器间的直接通信6.1.4 拓展案例 2&#xff1a;跨主机容器通信 6.2 配置与管理网络6.2.1 重点基础知识6.2.2 重点案例&#xff1a;配置 Flask 应用的…

【Java程序设计】【C00302】基于Springboot的校园失物招领管理系统(有论文)

基于Springboot的校园失物招领管理系统&#xff08;有论文&#xff09; 项目简介项目获取开发环境项目技术运行截图 项目简介 这是一个基于Springboot的校园失物招领网站&#xff0c;本系统有管理员以及用户二种角色权限&#xff1b; 系统整体功能有&#xff1a;操作日志管理、…