1.Two Sum

题目描述:简单难度

在这里插入图片描述
给定一个数组和一个目标和,从数组中找两个数字相加等于目标和,输出这两个数字的下标。

解法一 双层循环

简单粗暴些,两重循环,遍历所有情况看相加是否等于目标和,如果符合直接输出。

Java
public class Two_Sum {
	public static int[] twosum(int[] nums,int target) {
		int[] ans=new int[2];
		for(int i=0;i<nums.length;i++) {
			for(int j=i+1;j<nums.length;j++) {
				if(nums[i]+nums[j]==target) {
					ans[0]=i;
					ans[1]=j;
					return ans;
				}
			}
		}
		return ans;
	}
	public static void main(String args[]) {
		int[] nums= {2,7,11,15};
		int target=9;
		int[] ans=twosum(nums,target);
		for(int i:ans) {
			System.out.println(i);
		}
	}
}

在这里插入图片描述
时间复杂度:两层 for 循环,O(n²)
空间复杂度:O(1)

Python
class Solution(object):
    def twoSum(self, nums, target):
        ans=[]
        for i in range(len(nums)):
            for j in range(i+1,len(nums)):
                if(nums[i]+nums[j]==target):
                    ans.append(i)
                    ans.append(j)
                    return ans
        return ans片

在这里插入图片描述

解法二 双重哈希表

在上边的解法中看下第二个 for 循环步骤。

for(int j=(i+1);j<nums.length;j++){
	if(nums[i]+nums[j]==target){

我们换个理解方式:

for(int j=(i+1);j<nums.length;j++){ 
	sub=target-nums[i]
 	if(nums[j]==sub){

第二层 for 循环无非是遍历所有的元素,看哪个元素等于 sub ,时间复杂度为 O(n)。

有没有一种方法,不用遍历就可以找到元素里有没有等于 sub 的?

就是哈希表!

我们可以把数组的每个元素保存为 hashkey,下标保存为 hashvalue

这样只需判断 sub 在不在 hashkey 里就可以了,而此时的时间复杂度仅为 O(1)!

为什么哈希表查询此时的时间复杂度是 O(1),那么到底是什么保证了这一特性呢,这个就要从hashmap的底层存储结构说起,下来看一张图:
在这里插入图片描述
上面就是hashmap的底层存储示意图,要想查看一个键值对应的值,首先根据该键值的hash值找到该键的hash桶位置,即是tab[2]还是tab[1]等,计算某个键对应的哈希桶位置很简单,就是int pos = (n - 1) & hash,也就是hash%n,因为位运算效率高所以在hashmap实现时使用的是位运算这种方式,需要注意的是哈希桶的数量必须是2^n,所以hashmap一旦扩容必定是哈希桶数量翻番。

通过上面的描述,我们可以知道,根据键值找到哈希桶的位置时间复杂度为O(1),使用的就是数组的高效查询。

需要注意的地方是,还需判断找到的元素不是当前元素,因为题目里讲一个元素只能用一次。

在Java中,HashMap就是字典,put方法加入新数据,containKey查询key值是否存在,get方法查找value值。

Java
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 sub = target - nums[i];
            if(map.containsKey(sub) && map.get(sub) != i){
                return new int[]{i, map.get(sub)};
            }
        }
        return null;
    }
}

在这里插入图片描述

时间复杂度:比解法一少了一个 for 循环,降为 O(n)
空间复杂度:所谓的空间换时间,这里就能体现出来, 开辟了一个 hash table ,空间复杂度变为 O(n)

Python

其中,在python中,字典添加数据的方法为为update,查找key值的方式为 for key in dict,查找value值的方式为dict.get(key)

class Solution(object):
    def twoSum(self, nums, target):
        dic = {}
        ans = []
        for i in range(len(nums)):
            dic.update({nums[i]:i})
        for i in range(len(nums)):
            sub = target - nums[i]
            if(sub in dic and dic.get(sub) != i):
                ans.append(i)
                ans.append(dic.get(sub))
                return ans

在这里插入图片描述

总结

python字典(dict)添加数据格式

dict.update({key,value})

python列表(List)添加数据格式

list.append(key)

python列表(List)查找数据格式

list.get(key)#value

java字典(HashMap)添加数据格式

map.put(key,value)

java字典(HashMap)判断元素是否存在

map.containsKey(key)

java字典(HashMap)查找数据格式

map.get(key) //value

这道题目巧妙的使用了哈希表进行处理

参考文献
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

安替-AnTi

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值