LeetCode 高频题复盘(1)

文章介绍了多种编程问题,包括字符串无重复字符最长子串、链表反转、LRU缓存实现、数组操作(如K个最大元素和翻转链表)、三数之和、动态规划算法(最大子数组和)以及各种排序算法(快速排序、堆排序、归并排序和冒泡排序)。
摘要由CSDN通过智能技术生成

3. 无重复字符的最长子串


题目链接

class Solution:
    def lengthOfLongestSubstring(self, s: str) -> int:
        stack=[]
        max_cnt=0
        for 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=None
        cur=head
        while cur:
            temp=cur.next
            cur.next=pre
            pre=cur
            cur=temp
        return pre

146. LRU 缓存


题目链接

用到的数据结构:哈希表+双向链表

在这里插入图片描述

class ListNode:
    def __init__(self,key=None,value=None):
        self.key=key
        self.value=value
        self.pre=None
        self.next=None

class LRUCache:

    def __init__(self, capacity: int):
        self.capacity=capacity
        self.hashmap={}
        self.head=ListNode()
        self.tail=ListNode()
        self.head.next=self.tail
        self.tail.pre=self.head
    
    def move_to_tail(self,key):
        node=self.hashmap[key]
        node.pre.next=node.next
        node.next.pre=node.pre
        node.next=self.tail
        node.pre=self.tail.pre
        self.tail.pre.next=node
        self.tail.pre=node

    def 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 res
        else:
            return res.value

    def put(self, key: int, value: int) -> None:
        if key in self.hashmap:
            self.hashmap[key].value=value
            self.move_to_tail(key)
        else:
            if len(self.hashmap)==self.capacity:
                self.hashmap.pop(self.head.next.key)
                self.head.next=self.head.next.next
                self.head.next.pre=self.head
            newNode=ListNode(key,value)
            self.hashmap[key]=newNode
            newNode.next=self.tail
            newNode.pre=self.tail.pre
            self.tail.pre.next=newNode
            self.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=head
        pre=None
        while cur:
            temp=cur.next
            cur.next=pre
            pre=cur
            cur=temp
        return pre
    def reverseKGroup(self, head: Optional[ListNode], k: int) -> Optional[ListNode]:
        dummy=ListNode(next=head)
        pre,end=dummy,dummy
        while end.next:
            for _ in range(k):
                if end:
                    end=end.next
            if not end:
                break
            temp=end.next
            end.next=None
            start=pre.next
            pre.next=self.reverse(start)
            start.next=temp
            pre,end=start,start
        return 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 res
            if i>0 and nums[i]==nums[i-1]:
                continue
            L=i+1
            R=n-1
            while 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+=1
                    while L<R and nums[R]==nums[R-1]:
                        R-=1
                    L+=1
                    R-=1
                elif nums[i]+nums[L]+nums[R]>0:
                    R-=1
                else:
                    L+=1
        return 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]*n
        dp[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]
            dp[i]=max(dp[i-1],0)+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 list2
        if not list2:
            return list1
        if list1.val<list2.val:
            list1.next=self.mergeTwoLists(list1.next,list2)
            return list1
        else:
            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]=i
        return [] 

5. 最长回文子串


题目链接

class Solution:
    def longestPalindrome(self, s: str) -> str:
        n=len(s)
        dp= [[False]*n for _ in range(n)]
        begin=0
        max_len=1
        for 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]=True
                    if j-i+1>max_len:
                        max_len=j-i+1
                        begin=i
        return s[begin:begin+max_len]

912. 排序数组


题目链接

  1. 快速排序
class Solution:
    def sortArray(self, nums: List[int]) -> List[int]:
        self.quick(nums, 0, len(nums) - 1)
        return nums

    def quick(self, nums, left, right):
        if left >= right:
            return nums
        # 选择一个随机的索引作为pivot
        pivot_index = random.randint(left, right)
        # 将随机选择的pivot和最左侧的元素交换
        nums[left], nums[pivot_index] = nums[pivot_index], nums[left]
        pivot = nums[left]

        left0, right0 = left, right
        while left < right:
            while left < right and nums[right] >= pivot:
                right -= 1
            while left < right and nums[left] <= pivot:
                left += 1
            nums[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)
  1. 归并排序
class Solution:
    # 合并两个有序数组
    def merge(self,left,right):
        merged=[]
        i=j=0
        while i<len(left) and j<len(right):
            if left[i]<=right[j]:
                merged.append(left[i])
                i+=1
            else:
                merged.append(right[j])
                j+=1
        while i<len(left):
            merged.append(left[i])
            i+=1
        while j<len(right):
            merged.append(right[j])
            j+=1
        return merged
    # 划分左右数组
    def sortArray(self, nums: List[int]) -> List[int]:
        if len(nums)<=1:
            return nums
        mid=len(nums)//2
        left=self.sortArray(nums[:mid])
        right=self.sortArray(nums[mid:])
        return self.merge(left,right)
  1. 堆排序
class Solution:
    def adjust(self,nums,parent,length):
        """
        nums:待排序数组
        parent:父结点的索引
        length:参与调整的数组长度(结点个数)
        """
        child=parent*2+1
        while child<length:
            if child+1<length and nums[child+1]>nums[child]:
                child+=1
            if nums[parent]<nums[child]:
                nums[parent],nums[child]=nums[child],nums[parent]
                parent=child
                child=2*parent+1
            else:
                break

    def 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
  1. 冒泡排序
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);
  • 快速排序、堆排序是不稳定的,归并排序、冒泡排序是稳定的。
  • 5
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值