目录
- 3. 无重复字符的最长子串
- 206. 反转链表
- 146. LRU 缓存
- 215. 数组中的第K个最大元素
- 25. K 个一组翻转链表
- 15. 三数之和
- 53. 最大子数组和
- 21. 合并两个有序链表
- 1. 两数之和
- 5. 最长回文子串
- 912. 排序数组
3. 无重复字符的最长子串
题目链接
class Solution:def lengthOfLongestSubstring(self, s: str) -> int:stack=[]max_cnt=0for c in s:while c in stack:stack.pop(0)stack.append(c)if len(stack)>max_cnt:max_cnt=len(stack)return max_cnt
206. 反转链表
题目链接
# 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=Nonecur=headwhile cur:temp=cur.nextcur.next=prepre=curcur=tempreturn pre
146. LRU 缓存
题目链接
用到的数据结构:哈希表+双向链表
class ListNode:def __init__(self,key=None,value=None):self.key=keyself.value=valueself.pre=Noneself.next=Noneclass LRUCache:def __init__(self, capacity: int):self.capacity=capacityself.hashmap={}self.head=ListNode()self.tail=ListNode()self.head.next=self.tailself.tail.pre=self.headdef move_to_tail(self,key):node=self.hashmap[key]node.pre.next=node.nextnode.next.pre=node.prenode.next=self.tailnode.pre=self.tail.preself.tail.pre.next=nodeself.tail.pre=nodedef get(self, key: int) -> int:if key in self.hashmap:self.move_to_tail(key)res=self.hashmap.get(key,-1)if res==-1:return reselse:return res.valuedef put(self, key: int, value: int) -> None:if key in self.hashmap:self.hashmap[key].value=valueself.move_to_tail(key)else:if len(self.hashmap)==self.capacity:self.hashmap.pop(self.head.next.key)self.head.next=self.head.next.nextself.head.next.pre=self.headnewNode=ListNode(key,value)self.hashmap[key]=newNodenewNode.next=self.tailnewNode.pre=self.tail.preself.tail.pre.next=newNodeself.tail.pre=newNode# Your LRUCache object will be instantiated and called as such:
# obj = LRUCache(capacity)
# param_1 = obj.get(key)
# obj.put(key,value)
注意:
- 本题的数据结构:哈希表+双向链表
self
总是忘记写
215. 数组中的第K个最大元素
题目链接
class Solution:def findKthLargest(self, nums: List[int], k: int) -> int:return self.quickSelect(nums,k)def quickSelect(self,nums,k):pivot=random.choice(nums)big,equal,small=[],[],[]for num in nums:if num > pivot:big.append(num)elif num<pivot:small.append(num)else:equal.append(num)if k<=len(big):return self.quickSelect(big,k)elif k>len(nums)-len(small):return self.quickSelect(small,k-len(nums)+len(small))else:return pivot
25. K 个一组翻转链表
题目链接
# Definition for singly-linked list.
# class ListNode:
# def __init__(self, val=0, next=None):
# self.val = val
# self.next = next
class Solution:def reverse(self,head):cur=headpre=Nonewhile cur:temp=cur.nextcur.next=prepre=curcur=tempreturn predef reverseKGroup(self, head: Optional[ListNode], k: int) -> Optional[ListNode]:dummy=ListNode(next=head)pre,end=dummy,dummywhile end.next:for _ in range(k):if end:end=end.nextif not end:breaktemp=end.nextend.next=Nonestart=pre.nextpre.next=self.reverse(start)start.next=temppre,end=start,startreturn dummy.next
15. 三数之和
题目链接
class Solution:def threeSum(self, nums: List[int]) -> List[List[int]]:nums.sort()res=[]n=len(nums)for i in range(n):if nums[i]>0:return resif i>0 and nums[i]==nums[i-1]:continueL=i+1R=n-1while L<R:if nums[i]+nums[L]+nums[R]==0:res.append([nums[i],nums[L],nums[R]])while L<R and nums[L]==nums[L+1]:L+=1while L<R and nums[R]==nums[R-1]:R-=1L+=1R-=1elif nums[i]+nums[L]+nums[R]>0:R-=1else:L+=1return res
53. 最大子数组和
题目链接
class Solution:def maxSubArray(self, nums: List[int]) -> int:# dp[i]表示nums中下标从0到i的部分,最大的子数组和n=len(nums)if n==1:return nums[0]dp=[0]*ndp[0]=nums[0]for i in range(1,n):if dp[i-1]>0:dp[i]=dp[i-1]+nums[i]else:dp[i]=nums[i]return max(dp)
21. 合并两个有序链表
题目链接
# Definition for singly-linked list.
# class ListNode:
# def __init__(self, val=0, next=None):
# self.val = val
# self.next = next
class Solution:def mergeTwoLists(self, list1: Optional[ListNode], list2: Optional[ListNode]) -> Optional[ListNode]:if not list1:return list2if not list2:return list1if list1.val<list2.val:list1.next=self.mergeTwoLists(list1.next,list2)return list1else:list2.next=self.mergeTwoLists(list2.next,list1)return list2
1. 两数之和
题目链接
class Solution:def twoSum(self, nums: List[int], target: int) -> List[int]:hashmap={}for i,num in enumerate(nums):if target-num in hashmap:return [i,hashmap[target-num]]hashmap[num]=ireturn []
5. 最长回文子串
题目链接
class Solution:def longestPalindrome(self, s: str) -> str:n=len(s)dp= [[False]*n for _ in range(n)]begin=0max_len=1for i in range(n-1,-1,-1):for j in range(i,n):if s[i]==s[j] and (j-i<=2 or dp[i+1][j-1]):dp[i][j]=Trueif j-i+1>max_len:max_len=j-i+1begin=ireturn s[begin:begin+max_len]
912. 排序数组
题目链接
- 快速排序
class Solution:def sortArray(self, nums: List[int]) -> List[int]:self.quick(nums, 0, len(nums) - 1)return numsdef quick(self, nums, left, right):if left >= right:return nums# 选择一个随机的索引作为pivotpivot_index = random.randint(left, right)# 将随机选择的pivot和最左侧的元素交换nums[left], nums[pivot_index] = nums[pivot_index], nums[left]pivot = nums[left]left0, right0 = left, rightwhile left < right:while left < right and nums[right] >= pivot:right -= 1while left < right and nums[left] <= pivot:left += 1nums[left], nums[right] = nums[right], nums[left]# 恢复pivot到正确的位置nums[left0], nums[left] = nums[left], nums[left0]self.quick(nums, left + 1, right0)self.quick(nums, left0, left - 1)
- 归并排序
class Solution:# 合并两个有序数组def merge(self,left,right):merged=[]i=j=0while i<len(left) and j<len(right):if left[i]<=right[j]:merged.append(left[i])i+=1else:merged.append(right[j])j+=1while i<len(left):merged.append(left[i])i+=1while j<len(right):merged.append(right[j])j+=1return merged# 划分左右数组def sortArray(self, nums: List[int]) -> List[int]:if len(nums)<=1:return numsmid=len(nums)//2left=self.sortArray(nums[:mid])right=self.sortArray(nums[mid:])return self.merge(left,right)
- 堆排序
class Solution:def adjust(self,nums,parent,length):"""nums:待排序数组parent:父结点的索引length:参与调整的数组长度(结点个数)"""child=parent*2+1while child<length:if child+1<length and nums[child+1]>nums[child]:child+=1if nums[parent]<nums[child]:nums[parent],nums[child]=nums[child],nums[parent]parent=childchild=2*parent+1else:breakdef sortArray(self, nums: List[int]) -> List[int]:# 建立堆结构for i in range(len(nums)//2-1,-1,-1):self.adjust(nums,i,len(nums))for i in range(len(nums)-1,0,-1):nums[0],nums[i]=nums[i],nums[0]self.adjust(nums,0,i)return nums
- 冒泡排序
def bubble_sort(lis):n = len(lis)# 控制比较的轮数for j in range(n - 1):count = 0# 控制每一轮的比较次数# -1是为了让数组不要越界# -j是每一轮结束之后, 我们就会少比一个数字for i in range(n - 1 - j):if lis[i] > lis[i + 1]:lis[i], lis[i + 1] = lis[i + 1], lis[i]count += 1# 算法优化# 如果遍历一遍发现没有数字交换,退出循环,说明数列是有序的if count == 0:break
总结:
- 快速排序、堆排序、归并排序的时间复杂度都是 O(nlogn);
- 快速排序、堆排序是不稳定的,归并排序、冒泡排序是稳定的。