今天开始尝试接触力扣刷题。
看到题目是微微一笑,写代码是直接傻掉
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:
方法1 暴力枚举
class Solution(object): #创建一个类
def twoSum(self, nums, target): #定义一个函数
for i in range(len(nums)):
for j in range(i+1,len(nums)):
if nums[i]+nums[j] == target:
return [i,j]
没什么好说的,主要是得搞明白题目的要求
方法2 哈希表
class Solution(object):
def twoSum(self, nums, target):
hashmap_dict = dict() # 创建一个空字典用于存储数值和对应的索引
for index, value in enumerate(nums): # 遍历 nums 列表,得到每个元素的索引和数值
if (target - value) in hashmap_dict: # 检查字典中是否存在一个数,使其与当前数的和等于 target
return [hashmap_dict[target - value], index] # 如果存在,返回这个数的索引和当前数的索引
else:
hashmap_dict[value] = index # 如果不存在,将当前数值和索引存入字典
return [] # 如果遍历完所有元素后没有找到符合条件的数对,返回空列表
*假设 nums = [2, 7, 11, 15] 且 target = 9,代码的执行过程如下:
初始化 hashmap_dict 为一个空字典。
遍历 nums 列表:
第一次迭代:index = 0, value = 2
target - value = 9 - 2 = 7 不在 hashmap_dict 中,所以将 2: 0 存入字典。
第二次迭代:index = 1, value = 7
target - value = 9 - 7 = 2 在 hashmap_dict 中,所以返回 [0, 1]。
因此,代码正确地找到了和为 9 的两个数 2 和 7,它们的索引分别为 0 和 1。*
enumerate() 函数
enumerate() 函数用于将一个可遍历的数据对象(如列表、元组或字符串)组合为一个索引序列,同时列出数据和数据下标,一般用在 for 循环当中。
语法:
enumerate(sequence, [start=0])
参数
sequence -- 一个序列、迭代器或其他支持迭代对象。
start -- 下标起始位置。
返回值
返回 enumerate(枚举) 对象。
举个例子
a = [11,22,33,44,55,66,77]
for x,y in enumerate(a,2):
print(x, "=", y)
print
2 = 11
3 = 22
4 = 33
5 = 44
6 = 55
7 = 66
8 = 77
哈希表
散列表(Hash table,也叫哈希表),是根据关键码值(Key和value)而直接进行访问的数据结构。也就是说,它通过把关键码值映射到表中一个位置来访问记录,以加快查找的速度。这个映射函数叫做散列函数,存放记录的数组叫做散列表。
哈希冲突
即不同的key通过同一哈希函数产生了相同的哈希位置,H(key1)=H(key2),此时就会产生哈希冲突
2.字母异位词分组
题目要求:给你一个字符串数组,请你将 字母异位词 组合在一起。可以按任意顺序返回结果列表。
字母异位词 是由重新排列源单词的所有字母得到的一个新单词
示例 1:
输入: strs = ["eat", "tea", "tan", "ate", "nat", "bat"]
输出: [["bat"],["nat","tan"],["ate","eat","tea"]]
示例 2:
输入: strs = [""]
输出: [[""]]
class Solution(object):
def groupAnagrams(self,strs):
hash_table = dict() #建立一个空字典作为哈希表
for i in strs: #遍历输入字符串strs中的每个字符串i。
n = "".join(sorted(i)) #对于每个字符串,先通过sorted(i)函数对其字符进行排序,形成一个新的字符串n
if n in hash_table: #如果在哈希表中,则添加进去
hash_table[n].append(i)
else:
hash_table[n] = [i] #如果不在哈希表,就新建一个键值对,键是排序后的字符串,值是一个只包含当前字符串的列表。
return list(hash_table.values())#将hash_table字典中所有的值(也就是各个键对应的字符串列表)转换成列表,并将其作为结果返回。由于values()方法返回的是一个视图,可以直接迭代,但为了直接返回一个完整的列表,这里使用了list()函数进行转换。
.join方法
方法:用于将序列中的元素以指定的字符连接生成一个新的字符串
" ".join; ",".join; "-".join 这三个都可以当做分隔符
sort()和sorted()
sorted() 函数对所有可迭代的对象进行排序操作
1、返回值
sort()直接对原始序列进行排序,不会返回任何值。
sorted()返回一个新序列,其中包含排序后的元素。
2、原地排序
sort()是一个原地排序函数,即它直接修改原始序列。
sorted()是一个非原地排序函数,它返回一个新序列,而不修改原始序列。
3、关键字参数
sort()不支持关键字参数。
sorted()支持关键字参数,例如key、reverse,允许根据自定义规则排序。
4、用法
sort():my_list.sort()
sorted():sorted_list=sorted(my_list)
键盘行
题目要求:给你一个字符串数组 words ,只返回可以使用在 美式键盘 同一行的字母打印出来的单词。键盘如下图所示。
美式键盘 中:
第一行由字符 "qwertyuiop" 组成。
第二行由字符 "asdfghjkl" 组成。
第三行由字符 "zxcvbnm" 组成
示例 1:
输入:words = ["Hello","Alaska","Dad","Peace"]
输出:["Alaska","Dad"]
示例 2:
输入:words = ["omk"]
输出:[]
示例 3:
输:words = ["adsdf","sfd"]
输出:["adsdf","sfd"]
方法1
class Solution(object):
def findWords(self, words):
a = set('qwertyuiop') #创立三个集合
b = set('asdfghjkl')
c = set('zxcvbnm')
answer = [] #创建一个空的列表,用来放最终的输出答案
for word in words:
w = set(word.lower()) #全都是小写的
if w.issubset(a) or w.issubset(b) or w.issubset(c): #用issubset用于判断集合的所有元素是否都包含在指定集合中判断 W集合是否在a集合中或等等
answer.append(word) #如果是在answer列表中添加w
return answer #返回最终的答案
方法2
class Solution:
def findWords(self,words)
set1 = set('qwertyuiop')
set2 = set('asdfghjkl')
set3 = set('zxcvbnm')
ans=[]
for i in words:
x = set(i.lower())
if x<=set1 or x<=set2 or x<=set3:
ans.append(i)
return ans
子集判断:使用 <= 运算符来判断一个集合是否是另一个集合的子集,即前者的所有元素都在后者中。
超集判断:使用 >= 运算符来判断一个集合是否是另一个集合的超集,即后者的所有元素都在前者中。
是否是真子集:使用 < 运算符来判断一个集合是否是另一个集合的真子集,即前者是后者的子集但不相等。
是否是真超集:使用 > 运算符来判断一个集合是否是另一个集合的真超集,即后者是前者的子集但不相等。
issubset()
issubset() 方法用于判断集合的所有元素是否都包含在指定集合中,如果是则返回 True,否则返回 False。
方法:set.issubset(set)
返回布尔值,如果都包含返回 True,否则返回 False。
用法:set.issubset(set) ,判断括号外的集合是否都包含在括号内的集合中
3.罗马数字转整数
罗马数字包含以下七种字符: I, V, X, L,C,D 和 M。
字符 数值
I 1
V 5
X 10
L 50
C 100
D 500
M 1000
例如, 罗马数字 2 写做 II ,即为两个并列的 1 。12 写做 XII ,即为 X + II 。 27 写做 XXVII, 即为 XX + V + II 。
通常情况下,罗马数字中小的数字在大的数字的右边。但也存在特例,例如 4 不写做 IIII,而是 IV。数字 1 在数字 5 的左边,所表示的数等于大数 5 减小数 1 得到的数值 4 。同样地,数字 9 表示为 IX。这个特殊的规则只适用于以下六种情况:
I 可以放在 V (5) 和 X (10) 的左边,来表示 4 和 9。
X 可以放在 L (50) 和 C (100) 的左边,来表示 40 和 90。
C 可以放在 D (500) 和 M (1000) 的左边,来表示 400 和 900。
给定一个罗马数字,将其转换成整数。
示例 1:
输入: s = "III"
输出: 3
示例 2:
输入: s = "IV"
输出: 4
示例 3:
输入: s = "IX"
输出: 9
示例 4:
输入: s = "LVIII"
输出: 58
解释: L = 50, V= 5, III = 3.
示例 5:
输入: s = "MCMXCIV"
输出: 1994
解释: M = 1000, CM = 900, XC = 90, IV = 4.
class Solution(object):
def romanToInt(self, s):#在罗马数字转换中,左边数字大于右边数字,除了一些例外
dic = {'I':1,'V':5,'X':10,'L':50,'C':100,'D':500,'M':1000 }
# 字符:数值 创建罗马数字对应的字典,需要考虑特殊情侣,例如罗马数字IV值为4,
# 刚好等于右边罗马数字的值减左边罗马数字的值(前提是左边的数字小于右边的数字)
total = 0 #设置总数的默认值为0
a = len(s) #s为输入的罗马数字,a为罗马数字的长度
for i in range(a-1): #遍历字典,但范围不包括最后一个数字
if dic[s[i]] < dic[s[i+1]]: #如果左边的数字小于右边的数字,则减去s[i]这个数字
total -= dic[s[i]]
else: #如果左边的数字大于右边的数字,则加s[i]这个数字
total += dic[s[i]]
return total + dic[s[-1]] #返回总数 + s的最后一个罗马数字的值
4.最长回文子串
给你一个字符串 s,找到 s 中最长的回文子串。
示例 1:
输入:s = "babad"
输出:"bab"
解释:"aba" 同样是符合题意的答案。
示例 2:
输入:s = "cbbd"
输出:"bb"
class Solution:
def longestPalindrome(self, s):
if not s:
return ""
def center(left, right): #中心扩展法,定义两个变量
while left >= 0 and right < len(s) and s[left] == s[right]: #保证左侧和右侧都不会越界,且检查字符串left和right索引是否相同,如果相同继续向两侧循环
left -= 1 #每次left的索引都要自减1
right += 1 #每次right的索引自增1
return right - left - 1
#在循环的过程中,left和right处于不满足回文条件的位置,left会比实际回文子串的左边界小1,right则大1;循环结束后,left指向比回文子串左边界小1的位置,
#right比回文子串右边界大1的位置
#所以最后return的长度公式应该=(left-1)-(right+1)+1
#设我们在字符串 "racecar" 中找到回文子串 "aceca":扩展结束时,left 会是 0,right 会是 6。实际回文子串 "aceca" 的长度为 5,计算过程是:
# (right - left - 1) = 6 - 0 - 1 = 5。
start = 0
max_len = 0
for i in range(len(s)):
len1 = center(i, i)
len2 = center(i, i + 1)
cur_len = max(len1, len2)
# i遍历字符串,从0至len - 1
#调用 center(i, i),计算以 i 位置的字符为中心的最长回文子串的长度。这种情况下,回文子串的中心是单个字符,例如 "aba" 中的 "b"
#调用 center(i, i + 1),计算以 i 和 i + 1 两个位置之间的间隙为中心的最长回文子串的长度。这种情况下,回文子串的中心是两个相邻字符之间的空隙,例如 "abba" 中的 "bb"
#计算 len1 和 len2 的最大值,即当前索引 i 处可能的最长回文子串的长度
if cur_len > max_len:
max_len = cur_len
start = i - (cur_len - 1) // 2
#如果当前计算出的回文子串的长度 cur_len 大于已知的最长回文子串的长度 max_len,说明找到了一个新的、更长的回文子串
#更新 max_len 为当前找到的更长的回文子串的长度 cur_len,以便后续继续判断是否有更长的回文子串
#i 是当前中心位置的索引,而 cur_len 是以这个中心扩展得到的回文子串的长度。
#cur_len - 1 是回文子串的实际长度减去1(因为中心算作一个位置)。
#// 2 表示整除(即取商而忽略余数),这个操作计算出半径,即从中心向左扩展的长度。
#最终,i - (cur_len - 1) // 2 计算出这个回文子串的实际起点位置。
#假设 i = 2,cur_len = 3:对应的回文子串长度为 3,中心位置为 i = 2,那么起点应该是 2 - (3 - 1) // 2 = 1。
#这样 start 就指向了新的最长回文子串的起始位置
return s[start:start + max_len]
#py切片语法法
#假设 s = "babad",并且在循环结束后,start = 0,max_len = 3。则 s[start:start + max_len] 就等于 s[0:3],即 "bab"。
#这时,return "bab" 会将这个最长的回文子串返回。
To be continued ...