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]
方法一:暴力解法,通过两个for循环,然后进行一个判断来获得正确的答案,此方法复杂度较高为O(n^2) 注意:使用双重循环时间应注意迭代对象的起始。
class Solution:
def twoSum(self, nums: List[int], target: int) -> List[int]:
for i in range(0,len(nums)):
for j in range(i+1,len(nums)):
if nums[i] + nums[j] ==target:
return [i,j]
方法二:哈希表,建立一个哈希表,通过target-nums[i] 来判断是否哈希表内有答案,若无将该值添加进去。
class Solution:
def twoSum(self, nums: List[int], target: int) -> List[int]:
ind={} #建立一个哈希表
for i, num in enumerate(nums):
if target - num in ind: #判断是否在哈希表内
return [ind[target - num], i]
ind[nums[i]] = i
2.两数相加
给你两个非空的链表,表示两个非负的整数。它们每位数字都是按照 逆序 的方式存储的,并且每个节点只能存储 一位 数字。
请你将两个数相加,并以相同形式返回一个表示和的链表。
你可以假设除了数字 0 之外,这两个数都不会以 0 开头。
方法一:模拟解法
# Definition for singly-linked list.
# class ListNode:
# def __init__(self, val=0, next=None):
# self.val = val
# self.next = next
class Solution:
def addTwoNumbers(self, l1: Optional[ListNode], l2: Optional[ListNode]) -> Optional[ListNode]:
result = ListNode() #初始化一个新链表
carry, curr = 0, result #初始化进位,设置curr为指针
while l1 or l2 or carry:
s = (l1.val if l1 else 0) + (l2.val if l2 else 0) + carry
carry, val = divmod(s, 10)
curr.next = ListNode(val)
curr = curr.next
l1 = l1.next if l1 else None
l2 = l2.next if l2 else None
return result.next
方法二:递归
class Solution:
def addTwoNumbers(self, l1: Optional[ListNode], l2: Optional[ListNode]) -> Optional[ListNode]:
if l1 is None:
return l2
if l2 is NoneL
return l1
l1.val += l2.val
if l1.val >=10:
l1.next = self.addTwoNumbers(ListNode(l1.val // 10),l1.next)
l1.val %= 10
li.next = self.addTwoNumbers(l1.next,l2.next)
return l1
3.无重复字符的最长字串
给定一个字符串 s ,请你找出其中不含有重复字符的 最长子串 的长度。
示例 1:
输入: s = "abcabcbb"
输出: 3
解释: 因为无重复字符的最长子串是 "abc",所以其长度为 3。
示例 2:
输入: s = "bbbbb"
输出: 1
解释: 因为无重复字符的最长子串是 "b",所以其长度为 1。
这是一个经典的利用滑动窗口解决的问题,是属于不定长类型的问题。
class Solution:
def lengthOfLongestSubstring(self, s: str) -> int:
#Step1:定义需要维护的变量
max_len = 0
hashmap = {}
#Step2:定义窗口的首尾端,然后滑动窗口
right = 0
for left in range(len(s)):
#Step3:更新需要维护的变量,max_len,hashmap
hashmap[s[left]] = hashmap.get(s[left],0) +1
if len(hasnmap) == left-right+1:
max_len = max(max_len,left-right+1)
#Step4:根据题意,题目的窗口可变:这个时候一般涉及到窗口是否合法的问题
#这个时候要用一个while不断移动窗口左指针,从而剔除非法元素直到窗口合法
# 当窗口长度大于哈希表长度时候 (说明存在重复元素),窗口不合法
# 所以需要不断移动窗口左指针直到窗口再次合法, 同时提前更新需要维护的变量 (hashmap)
while left - right +1>len(hashmap):
head = s[start]
hashmap[head] -=1
if hashmap[head] ==0:
del hashmap[head]
right +=1
return max_len
4.寻找两个正序数组的中位数:
给定两个大小分别为 m 和 n 的正序(从小到大)数组 nums1 和 nums2。请你找出并返回这两个正序数组的 中位数 。
算法的时间复杂度应该为 O(log (m+n)) 。
示例 1:
输入:nums1 = [1,3], nums2 = [2]
输出:2.00000
解释:合并数组 = [1,2,3] ,中位数 2
我们把题目看为求第k小的数:
class Solution:
def findMedianSortedArrays(self, nums1: List[int], nums2: List[int]) -> float:
def dfs(nums1,i,nums2,j,k)->float:
if(len(nums1)-i)>len(nums2)-j:
return dfs(nums2,j,nums1,i,k)
if len(nums1)==i:
return nums2[j+k-1]
if k==1:
return min(nums1[i],nums2[j])
si = min(i + k // 2, len(nums1)) # 注意越界, 第一个列表不够取k/2个数的时候,全部取出来即可
sj = j + k//2
if nums1[si - 1] < nums2[sj - 1]:
return dfs(nums1, si, nums2, j, k - (si - i))
else:
return dfs(nums1, i, nums2, sj, k - (sj - j))
tot = len(nums1) + len(nums2) # 总长度
# 如果为奇数
if(tot & 1):
return dfs(nums1, 0, nums2, 0, tot // 2 + 1)
else:
left = dfs(nums1, 0, nums2, 0, tot // 2)
right = dfs(nums1, 0, nums2, 0, tot // 2 + 1)
return (left + right) / 2