2024.8.13 Python,哈希表(字典)哈希集合set

1. 两数之和

给定一个整数数组 nums 和一个整数目标值 target,请你在该数组中找出 和为目标值 target 的那 两个 整数,并返回它们的数组下标。
你可以假设每种输入只会对应一个答案。但是,数组中同一个元素在答案里不能重复出现。
你可以按任意顺序返回答案。
示例 1:
输入:nums = [2,7,11,15], target = 9
输出:[0,1]
解释:因为 nums[0] + nums[1] == 9 ,返回 [0, 1] 。
示例 2:
输入:nums = [3,2,4], target = 6
输出:[1,2]
示例 3:
输入:nums = [3,3], target = 6
输出:[0,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 []

这个是暴力解法,时间复杂度非常的大,不好。关于暴力解法我只记录一件事,那就是for i in range (n)这里,n为列表实际长度,那么range n其实是从0开始到n-1(含)不含n。前沾后不沾
解法二:哈希表

class Solution:
	def twoSum(self,nums:list[int],target:int)->list[int]:
		hashtable=dict()
		for i,num in enumerate(nums):
			if target-nums[i] in hashtable:
				return [hashtable[target-nums[i]],i]
			hashtable[nums[i]]=i
		return []

在这个例子里,列表为,标号对应元素,而hashtable是元素成了标签,也就是键,列表里的标号成了字典中的值
我最开始解这个题的思路是,把所有的列表元素直接对应进字典中建立哈希表,然后再搜索,这个例子中就是说,我直接建立空哈希表,搜索这个环节比写入要快,所以等于说我需要用更多的搜索而去少做写入操作
我在编写的时候有一个疑问,那就是第一次判断的时候,这个dict直接是空的,那岂不是第一个if就没有用,所以我把代码改成了这样,先写入,再判断。

class Solution:
	def twoSum(self,nums:list[int],target:int)->list[int]:
		hashtable=dict()
		for i,num in enumerate(nums):
			hashtable[nums[i]]=i
			if target-nums[i] in hashtable:
				return [hashtable[target-nums[i]],i]
			return []

然后去做测试用例的时候,对了60%,有对有错,那就是有情况没考虑清楚,我去看了一下测试用例, 其实说实话这个测试用例编的是真的好啊,三个测试用例就几乎涵盖了我需要的东西,我将详细记录出现的问题
测试用例里是这样的
示例 2:
输入:nums = [3,2,4], target = 6
输出:[1,2]
示例 3:
输入:nums = [3,3], target = 6
输出:[0,1]
那么我的输出出现了[0,0][0,0]
也就是说,我先写进去以后,他查找找到了自己,那么就出现0,0了,但是题目要求里说到:数组中同一个元素在答案里不能重复出现。也就是说重复下标是不合适的。那么我就又思考,如果我的代码[0,0][0,0]出错了,那么官方的代码就会出错在[1,1]。因为你想,测试用例如果是[2,3]的话,他不也是会找到自己吗,但是我测试了以后发现不会,因为他的逻辑是,比如3进来了,他在找自己的同伴,字典里就没有这个3本身,他自然不会找到自己,所以没找到,写进字典,找到了,直接输出。所以顺序一调换就ok了。

2.无重复字符的最长子串

给定一个字符串 s ,请你找出其中不含有重复字符的 最长 子串的长度。

示例 1:
输入: s = “abcabcbb”
输出: 3
解释: 因为无重复字符的最长子串是 “abc”,所以其长度为 3。
示例 2:
输入: s = “bbbbb”
输出: 1
解释: 因为无重复字符的最长子串是 “b”,所以其长度为 1。
示例 3:
输入: s = “pwwkew”
输出: 3
解释: 因为无重复字符的最长子串是 “wke”,所以其长度为 3。
请注意,你的答案必须是 子串 的长度,“pwke” 是一个子序列,不是子串
在这个题中,官方解答给出了一个新的概念叫做哈希集合,在python中的哈希集合叫做set(),其中set的用法如下:

# 创建空集合
empty_set = set()
# 从列表创建集合
numbers_set = set([1, 2, 3, 3, 4])
print(numbers_set)  # 输出: {1, 2, 3, 4}
# 从字符串创建集合
char_set = set("hello")
print(char_set)  # 输出: {'h', 'e', 'l', 'o'}
numbers_set = {1, 2, 3}
print(2 in numbers_set)  # 输出: True
print(4 in numbers_set)  # 输出: False
class Solution:
    def lengthOfLongestSubstring(self, s: str) -> int:
        occ=set()
        n=len(s)
        rk,ans=0,0
        for i in range (n):
            if i !=0:
                occ.discard(s[i-1])
            while rk<n and s[rk] not in occ:
                occ.add(s[rk])
                rk+=1
            ans=max(ans,rk-i)
        return ans

这个题就引入了先判断,再入库的思想,其实能说的不多,我做的时候,discard那里删错了,应该是删i-1的,导致删错了。学会使用debug了。

3.岛屿问题

给你一个由 ‘1’(陆地)和 ‘0’(水)组成的的二维网格,请你计算网格中岛屿的数量。岛屿总是被水包围,并且每座岛屿只能由水平方向和/或竖直方向上相邻的陆地连接形成。此外,你可以假设该网格的四条边均被水包围。
示例 1:
输入:grid = [
[“1”,“1”,“1”,“1”,“0”],
[“1”,“1”,“0”,“1”,“0”],
[“1”,“1”,“0”,“0”,“0”],
[“0”,“0”,“0”,“0”,“0”]
]
输出:1

示例 2:
输入:grid = [
[“1”,“1”,“0”,“0”,“0”],
[“1”,“1”,“0”,“0”,“0”],
[“0”,“0”,“1”,“0”,“0”],
[“0”,“0”,“0”,“1”,“1”]
]
输出:3
这个题涉及到了深度优先搜索和广度优先搜索的概念,确实是我没有接触过的东西,所以我就看了下bilibili的图示讲解,其实说白了就是,深度优先搜索是一条路走到黑,走不下去了就拐弯然后找下一个,像人去公园走路一样,这条路你走过了,就想绕一下找找没走过的路,广度优先搜索看到一个很好的解释叫做层次,把节点一画为第一层,和节点一相连的画为第二层,把和节点一相连的相连化为第三层,像树枝一样分支下去。
深度优先代码如下

class Solution:
    def dfs(self,grid,r,c):
        grid[r][c]=0
        nr,nc=len(grid),len(grid[0])
        for x,y in [(r-1,c),(r+1,c),(r,c-1),(r,c+1)]:
            if 0<=x<nr and 0<=y<nc and grid [x][y]=="1":
                self.dfs(grid,x,y)

    def numIslands(self,grid:List[List[str]])->int:
        nr=len(grid)
        if nr==0:
            return 0
        nc=len(grid[0])
        num_islands=0
        for r in range(nr):
            for c in range (nc):
                if grid[r][c]=="1":
                    num_islands+=1
                    self.dfs(grid,r,c)
        return num_islands

代码逻辑是这样的
1.先计算网格长宽,要是长为0,那直接输出无,要是有长那就有宽,就可以算了,用len(grid)和len(grid[0])这两个命令分别得出来nr和nc的值,以限制遍历的上限。
2.初始化岛屿数量。
3.遍历,遇见一个1就加一,同时开始运行迭代算法,让1周围的1都清零。
4.清零函数就是深度遍历函数,先置零,然后用for循环给四周检查有无1,没有则罢了,有就再次在一上运行清零函数,这样就可以做到遍历清零。

  • 3
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值