Open azl397985856 opened 2 years ago
思路: 两数之和,梦开始的地方。哈希表
func twoSum(nums []int, target int) []int { hash := map[int]int{} for i,x := range nums{ if out,ok := hash[target-x];ok{ return []int{out,i} }else{ hash[x] = i } } return nil } 时间复杂度O(n) 空间复杂度O(n)
class Solution {
public:
vector<int> twoSum(vector<int>& nums, int target) {
unordered_map<int, int> map;
// vector<int> res;
for (int i = 0; i < nums.size(); i++) {
int key = target - nums[i];
if (map.count(key)) return { map[key], i };
map[nums[i]] = i;
}
return {};
}
};
class Solution:
def twoSum(self, nums: List[int], target: int) -> List[int]:
dicts = dict()
for i in range(len(nums)):
if target - nums[i] in dicts.keys():
return [i, dicts[target-nums[i]]]
else:
dicts[nums[i]] = i
哈希表的应用
class Solution:
def twoSum(self, nums: List[int], target: int) -> List[int]:
hashmap={}
for i,num in enumerate(nums):
cp=target-num
if cp in hashmap:
return [hashmap[cp],i]
hashmap[num]=i
return []
var twoSum = function(nums, target) { let map = new Map(); let arr = []; nums.forEach((value,index) => { if(map.has(target - value) ) { arr = arr.concat([map.get(target - value),index]) ; } map.set(value,index);
}); return arr;
};
双循环 哈希表 哈希表优化
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};
}
}
}
return null;
}
public int[] twoSum(int[] nums, int target) {
HashMap<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++) {
if(map.containsKey(target-nums[i])){
return new int[]{i,map.get(target-nums[i])};
}
}
return null;
}
public int[] twoSum(int[] nums, int target) {
Map<Integer, Integer> map = new HashMap<>();
for (int i = 0; i < nums.length; i++) {
if (map.containsKey(nums[i])){
return new int[]{map.get(nums[i]), i};
}else{
map.put(target - nums[i], i);
}
}
return null;
}
代码
class Solution {
public int[] twoSum(int[] nums, int target) {
Map<Integer, Integer> map = new HashMap<>();
int n = nums.length;
for (int i = 0; i < n; ++i) {
if (map.containsKey(target - nums[i])) {
return new int[]{map.get(target - nums[i]), i};
}
map.put(nums[i], i);
}
// 返回一个长度为0的数组比直接返回null好,这样调用处就不用判断null了
return new int[0];
}
}
复杂度
class Solution {
public int[] twoSum(int[] nums, int target) {
int res[] = new int[2];
Map<Integer,Integer>map = new HashMap<>();
for(int i=0;i<nums.length;i++){
if(map.containsKey(target-nums[i])){
res[1] = i;
res[0] = map.get(target-nums[i]);
}
map.put(nums[i],i);
}
return res;
}
}
思路:暴力匹配 class Solution { public int[] twoSum(int[] nums, int target) { int[] arr =new int[2]; for(int i=0 ;i<nums.length-1;i++){ for(int j=i+1;j<nums.length;j++){ if(nums[i]+nums[j]==target){ arr[0]=i; arr[1]=j; } } } return arr; } } 时间复杂度:O(n2) 空间复杂度:O(1)
1.用map来存放{数组元素值,坐标}这样的键值对 2.运用逆向解法,即用target减去数组中的某个元素,然后来判断map中是否有相同的值,若有则存在满足条件的答案,返回两个坐标即可;若没有,则保存{数组中某个元素值,对应的坐标}到map对象中。依次遍历即可判断是否有满足条件的两个元素。
/**
* @param {number[]} nums
* @param {number} target
* @return {number[]}
*/
var twoSum = function(nums, target) {
const map = new Map()
for (let i = 0; i < nums.length; i++) {
let x = target - nums[i]
if(map.has(x)) {
return [map.get(x),i]
}
map.set(nums[i], i)
}
};
C++ Code:
class Solution {
public:
vector<int> twoSum(vector<int>& nums, int target) {
unordered_map<int,int> record;
for(int i=0; i< nums.size(); i++)
{
if(record.count(target - nums[i]))
{
return {record[target-nums[i]], i};
}
record[nums[i]] = i;
}
return {};
}
};
C++ Code:
class Solution {
public:
vector<int> twoSum(vector<int>& nums, int target) {
vector<int> res;
unordered_map<int, int> um;
for (int i = 0; i < nums.size(); ++i) {
if (um.find(target - nums[i]) != um.end()) {
return vector<int>{um[target - nums[i]], i};
}
um[nums[i]] = i;
}
return res;
}
};
复杂度分析
Day19 1 https://leetcode-cn.com/problems/two-sum/
class Solution {
public:
vector<int> twoSum(vector<int>& nums, int target) {
int n = nums.size();
unordered_map<int, int> mp;
for(int i = 0; i < n; ++i){
if(mp.find(target - nums[i]) != mp.end()){
return vector<int>({mp[target-nums[i]], i});
}else{
mp[nums[i]] = i;
}
}
return vector<int>({});
}
};
Complexity
哈希表法
哈希表能在 O(1) 的时间复杂度内找到一个数是否存在
/**
* 哈希表的做法
* 哈希表能在 O(1) 的时间复杂度内找到一个数是否存在
*
* 时间复杂度:O(n)
* 空间复杂度:O(n)
* @param nums
* @param target
* @return
*/
public int[] twoSum(int[] nums, int target) {
HashMap<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 other = target - nums[i];
// 不能是这个数本身
if (map.containsKey(other) && map.get(other) != i) {
return new int[]{map.get(other), i};
}
}
// 不存在
return new int[]{-1, -1};
}
创建一个哈希表,对于每一个value
,首先都要查询哈希表时否存在target-value
,不存在,说明另一个值不在哈希表里面,先把这个值加入到哈希表,后面有匹配的值会被取出来。
class Solution
{
/**
* @param Integer[] $nums
* @param Integer $target
* @return Integer[]
*/
function twoSum($nums, $target)
{
$hashtable = [];
foreach ($nums as $key => $value) {
$p = $hashtable[$target - $value] ?? false;
if ($p !== false) {
return [$p, $key];
}
$hashtable[$value] = $key;
}
return [];
}
}
// 12-30
class Solution {
public:
vector<int> twoSum(vector<int>& nums, int target) {
vector<int> ans(2,-1);
map<int, int> mp;
mp[nums[0]] = 0;
int len = nums.size();
for (int i = 1; i < len; i++) {
if (mp.count(target- nums[i])) {
ans[0] = i;
ans[1] = mp[target - nums[i]];
break;
}
else mp[nums[i]] = i;
}
return ans;
}
};
Day_19_两数之和.md
思路
经典第一道题,hashmap > > ```
代码
class Solution {
public int[]oSum(int[] nums, int target) {
///cun存的是下标
int[] res = new int[2];
if(nums ==null || nums.length==0){
return res;
}
//map,第一个存值,第二个存下标
Map<Integer,Integer> map = new HashMap<>();
for(int i = 0; i<nums.length;i++){
int temp = target-nums[i];
if(map.containsKey(temp)){
res[1]=i;
res[0]=map.get(temp);
}
map.put(nums[i],i);
}
return res;
}
}
复杂度分析
Java Code:
class Solution {
public int[] twoSum(int[] nums, int target) {
int[] res = new int[2];
Map<Integer, Integer> map = new HashMap<>();
for(int i = 0; i<nums.length; i++){
int tmp = target - nums[i];
if(map.containsKey(tmp)){
res[1] = i;
res[0] = map.get(tmp);
break;
}else{
map.put(nums[i], i);
}
}
return res;
}
}
复杂度分析
令 n 为数组长度。
哈希法即可。
时间复杂度:O(N); 如果用暴力法的话就是 O(N2)
空间复杂度:O(N);
var twoSum = function(nums, target) {
var hash = new Map()
for (let i = 0; i < nums.length; i++) {
var num = nums[i]
if (hash.has(num)) {
return [hash.get(num), i]
} else {
hash.set(target - num, i)
}
}
return []
};
暴力法就是双循环,最开始的想法就是类似冒泡排序。 哈希就是题目提示的双指针的感觉,
Map<Integer, Integer> map = new HashMap<>();
for (int i = 0; i < nums.length; i++) {
if (map.containsKey(nums[i]))
return new int[]{map.get(nums[i]), i};
map.put(target - nums[i], i);
}
return new int[]{};
复杂度分析 -时间复杂度:O(n) -空间复杂度:O(n)
@fupaopao
思路
为了能实现快速查找,建立一个哈希表,这个哈希表存储key : value = 列表中的值:值对应的下标
利用Python中的enumerate() 函数,提取值和下标,只因题目要求返回的是下标对的列表
当num[target - n] 即合适的下标 在哈希表里中,即可返回。否则添加到哈希表中
代码
python code:
class Solution: def twoSum(self, nums: List[int], target: int) -> List[int]: hashmap = {} for i, n in enumerate(nums): if target - n in hashmap: return [hashmap[target - n], i] hashmap[n] = i
负责度分析
令 n 为数组长度。
- 时间复杂度:O(n)
- 空间复杂度: O(n) 引入了一个哈希表
哈希表
JavaScript Code:
/**
* @param {number[]} nums
* @param {number} target
* @return {number[]}
*/
var twoSum = function (nums, target) {
let map = new Map();
for (let i = 0; i < nums.length; i++) {
const diff = target - nums[i];
console.log(diff);
// 16
// 11
// 7
if (map.has(diff)) {
return [map.get(diff), i]; // [1,2]
} else {
map.set(nums[i], i);
// 2,0
// 7,1
}
}
};
var nums = [2, 7, 11, 15];
twoSum(nums, 18);
console.log(twoSum(nums, 18));
复杂度分析
class Solution {
public int[] twoSum(int[] nums, int target) {
int n = nums.length;
for (int i = 0; i < n-1; i++){
for (int j = i + 1; j < n; j++){
int a = nums[i];
int b = nums[j];
int[] ans = new int[]{i,j};
if (a + b == target){
return ans;
}
}
}
return new int[0];
}
}
复杂度分析 时间复杂度:$0(N)$ 空间复杂度:$0(N)$
++
给定一个整数数组 nums
和一个整数目标值 target
,请你在该数组中找出 和为目标值 target
的那 两个 整数,并返回它们的数组下标。
你可以假设每种输入只会对应一个答案。但是,数组中同一个元素在答案里不能重复出现。
你可以按任意顺序返回答案。
进阶:你可以想出一个时间复杂度小于 O(n2)
的算法吗?
class Solution:
def twoSum(self, nums: List[int], target: int) -> List[int]:
hashtable = dict()
for i, num in enumerate(nums):
if target - num in hashtable:
return [hashtable[target - num], i]
hashtable[num] = i
return []
class Solution {
public:
vector<int> twoSum(vector<int>& nums, int target) {
unordered_map<int, int> hashtable;
for(int i = 0; i < nums.size(); i++){
auto it = hashtable.find(target - nums[i]);
if(it != hashtable.end()){
return {it->second, i};
}
hashtable[nums[i]] = i;
}
return {};
}
};
class Solution {
public int[] twoSum(int[] nums, int target) {
int n = nums.length;
for (int i = 0; i < n-1; i++){
for (int j = i + 1; j < n; j++){
int a = nums[i];
int b = nums[j];
int[] ans = new int[]{i,j};
if (a + b == target){
return ans;
}
}
}
return new int[0];
}
}
class Solution {
public int[] twoSum(int[] nums, int target) {
int[] arr = new int[2];
int len = nums.length;
for (int i = 0; i < len - 1; i++) {
for (int j = i + 1; j < len; j++) {
if (nums[i] + nums[j] == target) {
arr[0] = i;
arr[1] = j;
}
}
}
return arr;
}
}
双for循环时间复杂度为N2,不满足要求题目要求小于N2时间复杂度。
这里通过哈希表保存已经遍历过的target-当前元素的差值和下标。后续遍历时通过containsKey()方法(时间复杂度为O(1))找到另一个差值即可。
public class Day19 {
/**
* @param nums
* @param target
* @return
*/
public int[] twoSum(int[] nums, int target) {
int [] res = new int[2];
HashMap<Integer,Integer> map = new HashMap();
for (int i = 0; i < nums.length; i++) {
if(map.containsKey(nums[i])){
res[0] = i;
res[1] =map.get(nums[i]);
break;
}
map.put(target-nums[i],i);
}
return res;
}
}
时间复杂度:O(N)
空间复杂度:O(N)
https://leetcode-cn.com/problems/two-sum
哈希查找
class Solution:
def twoSum(self, nums: List[int], target: int) -> List[int]:
hashmap={}
for i,num in enumerate(nums):
if hashmap.get(target - num) is not None:
return [i,hashmap.get(target - num)]
hashmap[num] = i
复杂度分析:
时间复杂度:O(N)
空间复杂度:O(N)
哈希方法:
class Solution {
public:
vector
class Solution {
public int[] twoSum(int[] nums, int target) {
Map<Integer, Integer> hashtable = new HashMap<Integer, Integer>();
for (int i = 0; i < nums.length; ++i) {
if (hashtable.containsKey(target - nums[i])) {
return new int[]{hashtable.get(target - nums[i]), i};
}
hashtable.put(nums[i], i);
}
return new int[0];
}
}
时间复杂度 O(N) 空间复杂度 O(N)
https://leetcode-cn.com/problems/two-sum/
使用哈希表,对于每个元素nums[i]
,查询target-nums[i]
是否在哈希表中,不在则加入哈希表
class Solution {
public:
vector<int> twoSum(vector<int>& nums, int target) {
unordered_map<int, int> tar;
for(int i=0;i<nums.size();i++) {
if(tar.count(target-nums[i])){
return {tar[target-nums[i]], i};
}
tar.insert({nums[i],i});
}
return {};
}
};
复杂度分析
利用js的Map
var twoSum = function(nums, target) {
let hash = new Map();
for(let i = 0;i < nums.length;i++){
let differ = target - nums[i]
if(hash.has(differ)) {
return [hash.get(differ),i];
} else {
hash.set(nums[i], i)
}
}
};
时间复杂度:O(n)
空间复杂度:O(n)
val - index map. search for target - nums[i])
Time: O(n), n = nums.length
Space: O(n)
class Solution {
public int[] twoSum(int[] nums, int target) {
int[] indices = new int[2];
Map<Integer, Integer> valIndexMap = new HashMap<>();
for (int i = 0; i < nums.length; i++) {
if (valIndexMap.containsKey(target - nums[i])) {
indices[0] = i;
indices[1] = valIndexMap.get(target - nums[i]);
break;
} else {
valIndexMap.put(nums[i], i);
}
}
return indices;
}
}
class Solution(object):
def twoSum(self, nums, target):
num_dict = {}
for i, num in enumerate(nums):
if target-num in num_dict:
return [num_dict[target-num], i]
num_dict[num] = i
return False
func twoSum(nums []int, target int) []int { hashTable := map[int]int{} for i, x := range nums{ if p, ok:= hashTable[target - x]; ok { return []int{i, p} } hashTable[x] = i } return nil
}
思路 看到还是不能立马写出来,依然采用暴力的方法得到答案 代码
public int[] twoSum(int[] nums, int target) {
int n = nums.length;
for (int i = 0; i < n; ++i) {
for (int j = i + 1; j < n; ++j) {
if (nums[i] + nums[j] == target) {
return new int[]{i, j};
}
}
}
return new int[0];
}
}
复杂度 时间复杂度:O(N*N) 空间复杂度:O(1)
class Solution {
public int[] twoSum(int[] nums, int target) {
if(nums == null) {
return null;
}
Map<Integer, Integer> map = new HashMap<>();
for(int i = 0;i <= nums.length - 1;i++) {
int temp = target - nums[i];
if(map.containsKey(temp)) {
return new int[]{map.get(temp), i};
}
map.put(nums[i], i);
}
return new int[]{-1, -1};
}
}
思路:
暴力求解需要嵌套循环遍历,两个数的操作可以使用空间换时间;
步骤:
class Solution {
public int[] twoSum(int[] nums, int target) {
Map<Integer,Integer> map = new HashMap();
for(int i = 0;i<nums.length;i++){
if(map.containsKey(target-nums[i])){
return new int[]{map.get(target-nums[i]),i};
}
map.put(nums[i],i);
}
return null;
}
}
时间:O(n),n为数组长度;
空间:O(n),map保存数组值和索引;
用hash存储一遍值,然后逐个target - nums[i] 判断是否能在hash中获取
/**
* @param {number[]} nums
* @param {number} target
* @return {number[]}
*/
var twoSum = function(nums, target) {
const map = new Map();
nums.forEach((item, index) => {
map.set(item, index);
});
for (let i = 0; i < nums.length; i++) {
const j = map.get(target - nums[i]);
if (j !== undefined && j !== i) {
return [i, j];
}
}
return [];
};
时间O(N),空间O(N)
public 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};
return new int[]{-1, -1};
}
}
class Solution {
public:
vector<int> twoSum(vector<int>& nums, int target) {
int n = nums.size();
unordered_map<int, int> mp;
for(int i=0; i<n; i++){
if (mp.count(target-nums[i]) == 1){
return {i, mp[target-nums[i]]};
}
mp[nums[i]] = i;
}
return {0,0};
}
};
class Solution: def twoSum(self, nums: List[int], target: int) -> List[int]:
#0 n 0 n
c = {}
for ind, i in enumerate(nums):
if target - i in c:
return [ind, c[target - i]]
else:
c[i] = ind
return []
/**
* @param {number[]} nums
* @param {number} target
* @return {number[]}
*/
var twoSum = function(nums, target) {
let i = 0;
let map = new Map();
while(i < nums.length) {
map.set(nums[i], i);
i++;
}
for(let j = 0; j < nums.length;j++) {
if(map.has(target - nums[j]) && map.get(target - nums[j]) !== j) {
return [j, map.get(target - nums[j])]
}
}
};
哈希表空间换时间把复杂度降到O(n) class Solution: def twoSum(self, nums: List[int], target: int) -> List[int]: d = dict() for i in range(len(nums)): if nums[i] not in d: d[nums[i]] = i else: if nums[i]*2 == target: return [d[nums[i]],i] for i in range(len(nums)): if (target-nums[i]) in d and d[target-nums[i]] != i: return [i,d[target-nums[i]]]
哈希表存下每个taget-num的位置,每次都判断是否遇到了target-num
class Solution:
def twoSum(self, nums: List[int], target: int) -> List[int]:
remain_dict = {}
ans = []
for i,num in enumerate(nums):
if num in remain_dict.keys():
ans.append(i)
ans.append(remain_dict[num])
break
remain_dict[target-num] = i
return ans
时间复杂度:O(N) 空间复杂度:O(N)
class Solution:
def twoSum(self, nums: List[int], target: int) -> List[int]:
n = len(nums)
for i in range(n):
for j in range(i + 1, n):
if nums[i] + nums[j] == target:
return [i, j]
return []
'''
***复杂度分析***
- 时间复杂度:O(N^2),其中 N 是数组中的元素数量。最坏情况下数组中任意两个数都要被匹配一次。
- 空间复杂度:O(1)。
方法1 通过暴力遍历,便利没有个数组元素,挨个求和对比
方法2 有序列表 通过hash 记录差值,便利每一个是否包含这个差值,就是结果
def twoSum(self, nums: list[int], target: int) -> list[int]:
# """hash遍历,提高性能"""
sum_hash = {}
for i in range(len(nums)):
if(nums[i] in sum_hash):
return [sum_hash[nums[i]],i]
cha = target - nums[i]
sum_hash[cha] = i
return [0,0]
class Solution {
public int[] twoSum(int[] nums, int target) {
if(nums == null) {
return null;
}
Map<Integer, Integer> map = new HashMap<>();
for(int i = 0;i <= nums.length - 1;i++) {
int temp = target - nums[i];
if(map.containsKey(temp)) {
return new int[]{map.get(temp), i};
}
map.put(nums[i], i);
}
return new int[]{-1, -1};
}
}
class Solution: def twoSum(self, nums: List[int], target: int) -> List[int]: n = len(nums) for i in range(n): for j in range(i + 1, n): if nums[i] + nums[j] == target: return [i, j]
return []
class Solution {
public int[] twoSum(int[] nums, int target) {
Map<Integer, Integer> map = new HashMap<>();
for(int i = 0; i < nums.length; i++) {
if(map.containsKey(target - nums[i])) {
return new int[]{i, map.get(target - nums[i])};
}
map.put(nums[i], i);
}
return null;
}
}
复杂度分析
两数之和
入选理由
暂无
题目地址
https://leetcode-cn.com/problems/two-sum
前置知识
题目描述
给定 nums = [2, 7, 11, 15], target = 9
因为 nums[0] + nums[1] = 2 + 7 = 9 所以返回 [0, 1]
来源:力扣(LeetCode) 链接:https://leetcode-cn.com/problems/two-sum 著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。