LeetCode - 热题100 - day1
两数之和
给定一个整数数组 nums 和一个整数目标值 target,请你在该数组中找出 和为目标值 target 的那 两个 整数,并返回它们的数组下标。
你可以假设每种输入只会对应一个答案,并且你不能使用两次相同的元素。
你可以按任意顺序返回答案。
利用哈希表,key为数字,val为下标,当存在某个key与当前扫描到的num和为target,则找到,返回正确结果。
class Solution:
def twoSum(self, nums: List[int], target: int) -> List[int]:
hash = dict()
for i, num in enumerate(nums):
if target - num in hash:
return [i, hash[target - num]]
hash[num] = i
return []
字母异位词分组
给你一个字符串数组,请你将 字母异位词 组合在一起。可以按任意顺序返回结果列表。
字母异位词是通过重新排列不同单词或短语的字母而形成的单词或短语,并使用所有原字母一次。
解法1
核心是相同的字母组成,因此每个str排序后都是一样的可以作为哈希表的key,而val则是需要输出的数组。
class Solution:
def groupAnagrams(self, strs: List[str]) -> List[List[str]]:
# collections.defaultdict(list) 会在访问一个不存在的 key 时,自动初始化一个空list
mp = collections.defaultdict(list)
for s in strs:
sorted_s = "".join(sorted(s))
mp[sorted_s].append(s)
return list(mp.values())
解法2
同理,相同的字母组成即相同的字母数量,为每个str设一个list对应26个字母,值为字母数量,再进行tuple作为key记录strs。
class Solution:
def groupAnagrams(self, strs: List[str]) -> List[List[str]]:
mp = collections.defaultdict(list)
for s in strs:
letters = [0] * 26
for i in s:
letters[ord(i) - ord('a')] += 1
mp[tuple(letters)].append(s)
return list(mp.values())
最长连续序列
给定一个未排序的整数数组 nums ,找出数字连续的最长序列(不要求序列元素在原数组中连续)的长度。
请你设计并实现时间复杂度为 O(n) 的算法解决此问题。
把每一个数字当做开头找存在的最长序列,记录长度并比较找最大。这个方法确定了如果num-1存在,则num一定不会作为第一个数被算入,因此判定num-1不在nums中作为num为头元素算最长序列的条件。注意,此处在确认某个元素是否存在于nums中时,要先将nums转换为set(底层为哈希表),然后再进行判断,从而将查找的复杂度降低到 O(1),否则不符合题中要求的复杂度。
额外优化:序列性质决定最长的序列包含的元素以外的元素一定和该序列不连续,因此当某个最长长度超过num_set中元素数量的一半时,其他序列一定没有这个序列长(因为最多就是剩下所有元素连在一起),因此这个时候可以直接结束循环。
class Solution:
def longestConsecutive(self, nums: List[int]) -> int:
longest_ans = 0
num_set = set(nums)
for num in num_set:
# 如果存在num-1,则一定从num-1开始算长度,不存在则把这个num当做开头计算
if num - 1 not in num_set:
current_num = num
current_ans = 1
# 确定最长序列长度
while current_num + 1 in num_set:
current_num += 1
current_ans += 1
# 找更大
longest_ans = max(longest_ans, current_ans)
# 超过一半退出循环
if longest_ans * 2 > len(num_set):
break
return longest_ans
移动零
给定一个数组 nums,编写一个函数将所有 0 移动到数组的末尾,同时保持非零元素的相对顺序。
请注意 ,必须在不复制数组的情况下原地对数组进行操作。
除了0其他都应该放到前面,也就是说当把其他元素都放到前面的时候,剩下的都是0,因此只需要扫描一遍nums,同时用另一个指针(number_p)来记录下一个需要放元素的位置,每扫描到一个非0元素,放到number_p处,然后该指针指向下一个位置,最后扫描完以后从number_p开始放0一直放到最后即可。
class Solution:
def moveZeroes(self, nums: List[int]) -> None:
length = len(nums)
scan, number_p = 0, 0
while scan < length:
if nums[scan] != 0:
nums[number_p] = nums[scan]
number_p += 1
scan += 1
for i in range(number_p, length):
nums[i] = 0

浙公网安备 33010602011771号