方法一,暴力破解,时间复杂度O(n^2),空间复杂度O(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]
方法二,哈希表,时间复杂度O(n),空间复杂度O(n)
思路:向右枚举j,将值和下标存入哈希表,然后再枚举左边的数i,找到对应下标。
class Solution:
def twoSum(self, nums: List[int], target: int) -> List[int]:
h={}
# 向右枚举j,将值和下标存入哈希表,然后再枚举左边的数i,找到对应下标
for j,x in enumerate(nums):
if target-x in h:
return [h[target-x],j]
h[x]=j
方法一:把非零数都移到前面,其他数都赋值为0
时间复杂度:O(n),空间复杂度O(1)
class Solution:
def moveZeroes(self, nums: List[int]) -> None:
"""
Do not return anything, modify nums in-place instead.
"""
i=0
for j in range(len(nums)):
if nums[j]!=0:
nums[i]=nums[j]
i+=1
for x in range(i,len(nums)):
nums[x]=0
return nums
方法二: 双指针
思路:快慢指针,快指针在前面遍历,如果找到非零数,就与慢指针交换,慢指针向前走一步,直到所有非零元素都移动到前面。
时间复杂度O(n),空间复杂度O(1)
class Solution:
def moveZeroes(self, nums: List[int]) -> None:
"""
Do not return anything, modify nums in-place instead.
"""
l=0
for r in range(len(nums)):
if nums[r]!=0:
nums[l],nums[r]=nums[r],nums[l]
l+=1
return nums
双指针
左右指针,互相交换,然后各走一步,遍历完就完成了反转
class Solution:
def reverseString(self, s: List[str]) -> None:
"""
Do not return anything, modify s in-place instead.
"""
l,r=0,len(s)-1
while l
思路:index方法,遍历每一个字符,然后判断每一个字符首次出现的下标是否相等,如果相等的话,则是同构,不同的话则不是同构。
最坏的情况,因为index本身复杂度是n,时间复杂度O(n^2),空间复杂度O(1)
class Solution:
def isIsomorphic(self, s: str, t: str) -> bool:
for i in range(len(s)):
if s.index(s[i]) != t.index(t[i]):
return False
return True
思路:反转链表后,意思就是指针更改方向,创建一个pre指针赋为None,创建一个cur指针赋值为头,让cur指针指向pre指针,然后再移动。最后返回pre指针即链表的新头节点。
注意:要存储cur指向的指针,不然会断开后面的连接
时间复杂度O(n),空间复杂度O(1)
# Definition for singly-linked list.
# class ListNode:
# def __init__(self, val=0, next=None):
# self.val = val
# self.next = next
class Solution:
def reverseList(self, head: Optional[ListNode]) -> Optional[ListNode]:
pre=None
cur=head
while cur:
temp=cur.next
cur.next=pre
pre=cur
cur=temp
return pre
双指针,让两个指针指向尾部,模拟人工加法,处理好进位,然后再拼接起来
class Solution:
def addStrings(self, num1: str, num2: str) -> str:
res=""
i,j,carry=len(num1)-1,len(num2)-1,0
while i>=0 or j >=0:
# 超出索引范围直接赋值为0,相当于长度短的数字前面填0,方便后续计算
n1=int(num1[i]) if i>=0 else 0
n2=int(num2[j]) if j>=0 else 0
temp=n1+n2+carry
carry = temp//10
res=str(temp%10)+res
i,j=i-1,j-1
# 循环结束时,如果carry为1,则加到头部,没有则直接返回结果
return "1"+res if carry else res
方法一:直接用Python的内置函数index或者find,可以用来寻找字符串中子串,如果能找到,则返回第一个下标,否则抛出异常。
时间复杂度O(n)
class Solution:
def strStr(self, haystack: str, needle: str) -> int:
try:
return haystack.index(needle)
except:
return -1
方法二:切片
class Solution:
def strStr(self, haystack: 'str', needle: 'str') -> 'int':
for i in range(0, len(haystack) - len(needle) + 1):
if haystack[i:i+len(needle)] == needle:
return i
return -1
方法一:哈希表存储,用HashMap统计个数后,遍历的时候直接判断有没有相邻的数的个数统计答案即可
class Solution:
def findLHS(self, nums: List[int]) -> int:
cnt = defaultdict(int)
ans=0
for num in nums:
cnt[num]+=1
if num+1 in cnt:
ans=max(ans,cnt[num]+cnt[num+1])
if num-1 in cnt:
ans=max(ans,cnt[num]+cnt[num-1])
return ans
方法二:排序+双指针时间复杂度O(nlog(n)),空间复杂度O(1)
class Solution:
def findLHS(self, nums: List[int]) -> int:
nums.sort()
left=0
res=0
for right in range(len(nums)):
if nums[right]-nums[left]>1:
left+=1
if nums[right]-nums[left]==1:
res=max(res,right-left+1)
return res
方法一:哈希集合,将数组转化为集合(会去掉重复元素),然后判断前后长度是否一致
class Solution:
def containsDuplicate(self, nums: List[int]) -> bool:
s=set(nums)
if len(s)!=len(nums):
return True
else:
return False
方法二:哈希表
class Solution:
def containsDuplicate(self, nums: List[int]) -> bool:
numset={}
for i in nums:
if i not in numset:
numset[i]=1
else:
return True
return False
方法一:Counter法,统计字符串中每一个字符出现次数,然后遍历到第一个字符直接返回下标
时间复杂度:O(n^2),空间复杂度O(1)
class Solution:
def firstUniqChar(self, s: str) -> int:
l=Counter(s)
for i in s:
if l[i]==1:
return s.index(i)
return -1
方法二:哈希表,用哈希表存储每个字符,如果出现次数大于1则值为False,等于1则为True
class Solution:
def firstUniqChar(self, s: str) -> int:
dic = {}
for c in s:
dic[c] = not c in dic
for i, c in enumerate(s):
if dic[c]: return i
return -1
快慢双指针,让快指针在前面探路,发现不重复元素,就放到慢指针后面,慢指针就往前一步,一直到遍历完整张表。此时从head到slow都是不重复元素,再断开slow后面的指针,即可去重。
# Definition for singly-linked list.
# class ListNode:
# def __init__(self, val=0, next=None):
# self.val = val
# self.next = next
class Solution:
def deleteDuplicates(self, head: Optional[ListNode]) -> Optional[ListNode]:
slow,fast=head,head
if head is None:
return None
while fast:
if fast.val!=slow.val:
slow.next=fast
slow=slow.next
fast=fast.next
slow.next=None
return head
快慢指针,同上一题
class Solution:
def removeDuplicates(self, nums: List[int]) -> int:
if len(nums)==0:
return 0
slow,fast=0,0
while fast
方法一:Python内置函数zip,可以把多个序列中的元素打包成一个元组,zip(*可迭代对象)
例如,flower,float,flew是三个数,使用zip函数处理后,
[f,f,f],[l,l,l].[o,o,e]...,因此只需要判断这些序列去重后长度是否为1,即可判断是否能作为公共前缀
class Solution:
def longestCommonPrefix(self, strs: List[str]) -> str:
l=0
for i in zip(*strs):
if len(set(i))>1:
break
l+=1
return strs[0][:l]
括号匹配,用栈来做最佳
方法一:栈+if-else循环
时间复杂度O(n),空间复杂度是O(n)
class Solution:
def isValid(self, s: str) -> bool:
if len(s)%2!=0:
return False
stk=[]
for c in s:
if c=="(":
stk.append(")")
elif c=="[":
stk.append("]")
elif c=="{":
stk.append("}")
elif not stk or stk.pop()!=c:
return False
return not stk
方法二:栈+哈希表
思路:使用哈希表存储,键是左括号,值是右括号,遍历字符串,当遍历字符在哈希表中,将值压入栈中;如果栈为空,说明只有右括号,或者出栈元素跟当前元素不同,说明不匹配。
时空复杂度都是O(n)
class Solution:
def isValid(self, s: str) -> bool:
if len(s)%2!=0:
return False
stk=[]
mp={'(':')','[':']','{':'}'}
for c in s:
if c in mp:
stk.append(mp[c])
elif not stk or stk.pop()!=c:
return False
return not stk
对撞双指针,将元音字母顺序交换
class Solution:
def reverseVowels(self, s: str) -> str:
# a e i o u #元音元素
dic = {'a','e','i','o','u','A','E','I','O','U'} #大小写元音元素集合作为判断依据
pol = 0 #左指针
por = len(s)-1 #右指针
s_ = list(s) #str类型数据无法直接查询in和not in,转换为list
while pol < por: #左右指针交错循环停止
if s_[pol] in dic and s_[por] in dic: #左右指针所指元素均在集合中
s_[pol], s_[por] = s_[por], s_[pol] #交换左右指针所指元素
por -= 1 #右指针左移
pol += 1 #左指针右移
if s_[por] not in dic: #右指针所指元素不在集合中
por -= 1 #右指针左移
if s_[pol] not in dic: #左指针所指元素不在集合中
pol += 1 #左指针右移
return ''.join(s_) #返回str格式数据
def binary_to_decimal(binary_array):
# 将数组转换成字符串
binary_str = ''.join(str(bit) for bit in binary_array)
# 判断是否为负数
is_negative = binary_str[0] == '1'
if is_negative:
# 对于负数,转换为原码后计算
inverted = ['0' if b == '1' else '1' for b in binary_str]
inverted_str = ''.join(inverted)
# 加1操作
decimal_value = -int(inverted_str, 2) + 1
else:
# 正数直接转换
decimal_value = int(binary_str, 2)
return decimal_value
# 示例
binary_array = [1, 1, 1, 1] # 表示-1(假设字长为4)
print(binary_to_decimal(binary_array)) # 输出: -1
# Definition for a binary tree node.
# class TreeNode:
# def __init__(self, x):
# self.val = x
# self.left = None
# self.right = None
class Solution:
def invertTree(self, root: TreeNode) -> TreeNode:
if not root:
return None
queue=[root]
while queue:
node=queue.pop(0)
if node.left:
queue.append(node.left)
if node.right:
queue.append(node.right)
node.left,node.right=node.right,node.left
return root
先给数组排序,固定好一个值,再创建两个对撞指针,遍历整张表,然后删除重复的元素。
class Solution:
def threeSum(self, nums: List[int]) -> List[List[int]]:
nums.sort()
res = []
n=len(nums)
for i in range(n-2):
x=nums[i]
if i>0 and x==nums[i-1]:
continue
l=i+1
r=n-1
while l0:
r-=1
else:
res.append([x,nums[l],nums[r]])
l+=1
# 删除重复元素
while l
class Solution:
def reverseWords(self, s: str) -> str:
# 删除首尾空格
s=s.strip()
# 分割字符串
strs=s.split()
# 翻转单词列表
strs.reverse()
return " ".join(strs)
新建一个链表,使用虚拟头结点,然后计算两条链表的值,处理好进位
# 注意:python 代码由 chatGPT 根据我的 java 代码翻译。
# 本代码的正确性已通过力扣验证,如有疑问,可以对照我的 java 代码查看。
class Solution:
def addTwoNumbers(self, l1: ListNode, l2: ListNode) -> ListNode:
# 在两条链表上的指针
p1, p2 = l1, l2
# 虚拟头结点(构建新链表时的常用技巧)
dummy = ListNode(-1)
# 指针 p 负责构建新链表
p = dummy
# 记录进位
carry = 0
# 开始执行加法,两条链表走完且没有进位时才能结束循环
while p1 is not None or p2 is not None or carry > 0:
# 先加上上次的进位
val = carry
if p1 is not None:
val += p1.val
p1 = p1.next
if p2 is not None:
val += p2.val
p2 = p2.next
# 处理进位情况
carry = val // 10
val = val % 10
# 构建新节点
p.next = ListNode(val)
p = p.next
# 返回结果链表的头结点(去除虚拟头结点)
return dummy.next
滑动窗口
class Solution:
def lengthOfLongestSubstring(self, s: str) -> int:
ans = left = 0
window = set() # 维护从下标 left 到下标 right 的字符
for right, c in enumerate(s):
# 如果窗口内已经包含 c,那么再加入一个 c 会导致窗口内有重复元素
# 所以要在加入 c 之前,先移出窗口内的 c
while c in window: # 窗口内有 c
window.remove(s[left])
left += 1 # 缩小窗口
window.add(c) # 加入 c
ans = max(ans, right - left + 1) # 更新窗口长度最大值
return ans
创建一个列表,创建一个空单调栈,倒着遍历温度,如果当前栈中元素小于当前温度,则出栈,直到找到大于当前温度的元素,如果栈为空说明没有,则赋值为0,否则赋值为栈顶元素-当前下标
时间复杂度O(n),空间复杂度是O(n)
class Solution:
def dailyTemperatures(self, temperatures):
n = len(temperatures)
res = [0]*n
# 这里放元素索引,而不是元素
s = []
# 单调栈模板
for i in range(n-1, -1, -1):
while s and temperatures[s[-1]] <= temperatures[i]:
s.pop()
# 得到索引间距
res[i] = 0 if not s else s[-1] - i
# 将索引入栈,而不是元素
s.append(i)
return res
class Solution:
def deleteDuplicates(self, head: Optional[ListNode]) -> Optional[ListNode]:
cur = dummy = ListNode(next=head)
while cur.next and cur.next.next:
val = cur.next.val
if cur.next.next.val == val:
while cur.next and cur.next.val == val:
cur.next = cur.next.next
else:
cur = cur.next
return dummy.next
思路:初始化一个值,表示当前能到达的最大位置,然后遍历nums,如果max_i大于当前下标,且i+jump大于当前能到达最大位置,则更新,最后输出能否到达尾部。
时间复杂度O(n),空间复杂度O(1)
class Solution:
def canJump(self, nums: List[int]) -> bool:
max_i=0
for i,jump in enumerate(nums):
if max_i>=i and i+jump>max_i:
max_i=i+jump
return max_i>=len(nums)-1
class Solution:
def subarraySum(self, nums: List[int], k: int) -> int:
s = [0] * (len(nums) + 1)
for i, x in enumerate(nums):
s[i + 1] = s[i] + x
ans = 0
cnt = defaultdict(int)
for sj in s:
ans += cnt[sj - k]
cnt[sj] += 1
return ans
class Solution:
def maxProfit(self, prices: List[int]) -> int:
ans = 0
min_pirce = prices[0]
for p in prices:
ans = max(ans, p - min_pirce)
min_pirce = min(min_pirce, p)
return ans
class Solution:
def numRescueBoats(self, people: List[int], limit: int) -> int:
if people is None or len(people)==0:
return 0
# 创建对撞指针
p1 = 0
p2 = len(people)-1
res = 0
people.sort()
while p1<=p2:
# 如果头和尾相加小于限制,则头指针+1,表示可以坐一艘船
if people[p1]+people[p2]<=limit:
p1+=1
# 如果超重,则尾指针-1,表示尾部单独坐一艘船
p2-=1
res+=1
return res
R = (
("", "I", "II", "III", "IV", "V", "VI", "VII", "VIII", "IX"), # 个位
("", "X", "XX", "XXX", "XL", "L", "LX", "LXX", "LXXX", "XC"), # 十位
("", "C", "CC", "CCC", "CD", "D", "DC", "DCC", "DCCC", "CM"), # 百位
("", "M", "MM", "MMM"), # 千位
)
class Solution:
def intToRoman(self, num: int) -> str:
return R[3][num // 1000] + R[2][num // 100 % 10] + R[1][num // 10 % 10] + R[0][num % 10]