数据结构之狂刷Leetcode

贪心算法

采用贪心的策略保证每次操作都是局部最优,使其尽可能的多(但不一定是最多的)

分配问题

455.Assign Cookies分发饼干(easy)

在这里插入图片描述

"""
思路:用最小且能饱腹的饼干分给饥饿度最小的孩子,达到资源最大化
"""
class Solution(object):
    def findcontentchildren(self,g,s):
        g = sorted(g)       #饥饿度
        s = sorted(s)       #饼干
        childcount = cookies = 0
        #还有孩子或饼干没有分配完则继续
        while (childcount < len(g)) and (cookies < len(s)): 
        #每次给饥饿度最小的孩子分配最小且能饱腹的饼干           
              if g[childcount] <= s[cookies]:        
                 childcount += 1       #能饱腹,则喂饱孩子数+1
                 cookies += 1          #若不能饱腹,则该饼干对之后其他孩子都无效,消耗饼干数+1
        return childcount              #返回喂饱孩子个数
135.Candy分发糖果(hard)

在这里插入图片描述

"""
思路:两次遍历,所有孩子初始化糖果数为1
先从左往右遍历,右边的孩子比左边的评分高,则右边的糖果数为左边糖果数+1
再从右往左遍历,左边的孩子比右边的评分高且左边当前糖果数不大于右边,则左边糖果数为右边糖果数+1
"""
class Solution:
    def candy(self, ratings: List[int]) -> int:
        n = len(ratings)            #人数
        candy_nums = [1] * n        #糖果数全部初始化为1
        #从左开始遍历
        for i in range(1,n):        
            if ratings[i] > ratings[i-1]:           #右大于左
                candy_nums[i] = candy_nums[i-1]+1
            else:
                candy_nums[i] = 1
        #从右开始遍历        
        for i in range(n-1,0,-1):           #1到n的倒序
            if ratings[i-1] > ratings[i]:
                candy_nums[i-1] = max(candy_nums[i-1],candy_nums[i]+1)            
        return sum(candy_nums)
605.CanPlaceFlowers种花问题(easy)

在这里插入图片描述

"""
思路:花坛列表首尾加0(不影响种花),找出0位置,其左右两端都为0,则种花数+1,当前位置更新为1,进行循环
"""
class Solution:
    def canPlaceFlowers(self, flowerbed: List[int], n: int) -> bool:
        count = 0
        flowerbed = [0]+flowerbed+[0]        
        for i in range(1,len(flowerbed)-1):
            if flowerbed[i] == 0 and flowerbed[i+1] == 0 and flowerbed[i-1] == 0:
                count+=1
                flowerbed[i] = 1
        if count >= n:
            return True
        return False
860.柠檬水找零(easy)(增)

在这里插入图片描述

"""
思路:if条件语句进行判断
"""
class Solution:
    def lemonadeChange(self, bills: List[int]) -> bool:
        five,ten,twenty = 0,0,0
        for i in bills:
            if i == 5:
                five += 1
            elif i == 10 and five >= 1:
                if five < 1: return False
                five -= 1
                ten += 1
            else:
                if ten >= 1 and five >= 1:
                    five -= 1
                    ten -= 1
                    twenty += 1
                elif five >= 3:
                    five -= 3
                    twenty += 1
                else:
                    return False
        return True

区间问题

452.最少箭射气球(medium)

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

点击这里观看B站讲解视频

class Solution:
    def findMinArrowShots(self, points: List[List[int]]) -> int:
        if not points:
            return 0
        points.sort(key = lambda x:x[1])          #以右坐标排序
        count = 1                    #先射一箭
        biu = points[0][1]           #射箭位置为第一个球的右坐标
        for ball in points:
            if ball[0] <= biu:       #如果球的位置在射箭位置的左侧则同时射落两个
               continue
            else:
                count += 1           #否则需要再次射箭
                biu = ball[1]        #射箭位置为这个球的右坐标
        return count
435.无重叠区间(medium)

在这里插入图片描述

"""
思路:对区间以右坐标为准进行排序,首个区间就是右坐标最小的区间,找出与首个区间不重叠且右坐标最小的区间(其左坐标大于首区间右坐标即不重叠),进行遍历找出所有不重叠区间
"""
class Solution:
    def eraseOverlapIntervals(self, intervals: List[List[int]]) -> int:
        intervals.sort(key = lambda x: x[1])         #以右坐标排序
        cur,ok = 0,1
        n = len(intervals)
        for i in range(1,n):                  
            if intervals[i][0] >= intervals[cur][1]:   #左坐标大于最小右坐标即不重叠
               ok += 1
               cur = i
        return n-ok

链表

206.反转链表(easy)

在这里插入图片描述

class Solution:
    def reverseList(self,head):
        if head == None or head.next == None:
            return head
        pre = None
        cur = head
        while cur:
            x = cur.next
            cur.next = pre
            pre = cur
            cur = x
        return pre
21.合并两个有序链表(easy)

在这里插入图片描述

"""
思路:先设置一个哨兵节点pre,若l1 当前节点的值小于等于 l2 ,就把 l1 当前的节点接在 pre 节点的后面同时将 l1 指针往后移一位。否则,对 l2 做同样的操作。不管将哪一个元素接在了后面,都需要把 pre 向后移一位。直到l1,l2指向null
"""
class Solution:
    def mergeTwoLists(self, l1: ListNode, l2: ListNode) -> ListNode:
        prehead = ListNode(-1)
        pre = prehead
        while l1 and l2:
            if l1.val <= l2.val:     #l1节点的值小于l2
                pre.next = l1        #pre指针下一节点指向l1
                l1 = l1.next         #l1指针后移一位
            else:                    #l2节点的值小于l1
                pre.next = l2        #pre指针下一节点指向l2
                l2 = l2.next         #l2指针后移一位   
            pre = pre.next           #pre指针后移
        # 合并后 l1 和 l2 最多只有一个还未被合并完,我们直接将链表末尾指向未合并完的链表即可  
        if l1 is not None:
            pre.next = l1
        else:
            pre.next = l2
        return prehead.next
234.回文链表(easy)

在这里插入图片描述

"""
思路:遍历链表将值复制到数组列表中。我们用 current_node 指向当前节点。每次迭代向数组添加 current_node.val,并更新 current_node = current_node.next,当 current_node = null 时停止循环。比较列表中的节点地值是否回文
"""
class Solution:
    def isPalindrome(self, head: ListNode) -> bool:
        val = []
        current_node = head
        while current_node:
            val.append(current_node.val)
            current_node = current_node.next
        return val == val[::-1]
83.删除排序链表重复值(easy)

在这里插入图片描述

"""
下一节点的值不等于该节点的值则指针下移,若相等,则该点指针指向下下个节点
"""
class Solution:
    def deleteDuplicates(self, head: ListNode) -> ListNode:
        cur = head
        if not head:
            return head
        while cur.next:
            if cur.next.val == cur.val:
                cur.next = cur.next.next
            else:
                cur = cur.next
        return head

在这里插入图片描述

"""
Method 1
思路:使用快慢指针的方法,先定义一个虚拟节点dummyhead,让快指针先走n步,然后快慢指针再一起走,当快指针走到链表最后指向空的时候,慢指针的下一个节点即为要删除节点,此时让慢指针指向下下个节点即可。
"""
class Solution:
    def removeNthFromEnd(self, head: ListNode, n: int) -> ListNode:
        dummyhead = ListNode(0,head)     #定义一个虚拟节点0,快慢指针都从虚拟节点开始
        fast = dummyhead
        slow = dummyhead
        #进行循环,让快指针先走n步
        i = 0
        while i < n:
            fast = fast.next
            i += 1
        #快慢指针一起走直到快指针为空
        while fast.next is not None:
            fast = fast.next
            slow = slow.next
        #删除节点
        slow.next = slow.next.next
        return dummyhead.next
"""
Method 2
思路:首先从头节点开始对链表进行一次遍历,得到链表的长度 L。随后我们再从头节点开始对链表进行一次遍历,当遍历到第 L-n+1个节点时,它就是我们需要删除的节点。
"""
class Solution:
    def removeNthFromEnd(self, head: ListNode, n: int) -> ListNode:
        def getLength(head: ListNode) -> int:
            length = 0
            while head:
                length += 1
                head = head.next
            return length
        
        dummy = ListNode(0, head)
        length = getLength(head)
        cur = dummy
        for i in range(1, length - n + 1):
            cur = cur.next
        cur.next = cur.next.next
        return dummy.next
328.奇偶链表(medium)

在这里插入图片描述

"""
思路:分离奇偶链表,最后将两个链表进行合并。
第一个节点为head奇数链表的头结点,它的下一节点为偶数,是偶数链表的头结点
"""
class Solution:
    def oddEvenList(self, head: ListNode) -> ListNode:
        if not head:
            return head
        evenhead = head.next
        odd, even = head, evenhead
        while even and even.next:
            odd.next = even.next
            odd = odd.next
            even.next = odd.next
            even = even.next
        odd.next = evenhead
        return head

KMP算法

28.实现strStr() (easy)

def strStr(haystack, needle):
        if len(needle) == 0:
            return 0
        m,n = len(haystack), len(needle)
        #1.求next数组
        nxt = [0] * n
        j = 0
        for i in range(1,n):
            while j > 0 and needle[i] != needle[j]:
                j = nxt[j-1]
            if needle[i] == needle[j]:
                j += 1
                nxt[i] = j
        #return nxt
        #2.匹配字符串
        j = 0
        for i in range(0, m):
            while j>0 and haystack[i] != needle[j]:
                j = nxt[j - 1]
            if haystack[i] == needle[j]:
                j += 1
            if j == n:
                return i - n + 1
        return -1
strStr('abxabcabcaby','abcaby')

二分查找

704.二分查找(easy)

在这里插入图片描述
在这里插入图片描述

点击这里观看B站讲解视频

"""
思想:把nums分为大致相等的两部分,取nums[mid]与target作比较:
若nums[mid]=t,则找到t,返回mid值即为下标
若nums[mid]<t,则在mid右半边继续寻找t
若nums[mid]>t,则在mid左半边继续寻找t
high<low时跳出循环
"""
class Solution(object):
    def search(self, nums, target):
        left,right = 0,len(nums)-1
        while left <= right:
            mid = (left+highright)//2
            if nums[mid] < target:   #若中间值小于目标值,则low移到mid右边,再次循环更新mid
                left = mid + 1
            elif nums[mid] > target:   #若中间值大于目标值,则high移到mid左边,再次循环更新mid
                right = mid - 1
            else:
                return mid
        return -1
69.sqrt()

在这里插入图片描述

class Solution(object):
    def mySqrt(self, x):
        left,right = 0, x
        while left <= right:
            mid = (left+right)//2
            if mid**2 < x:
                left = mid+1
            elif mid**2 > x:
                right = mid-1
            else:
                return mid
        return right     #right>left时跳出循环,mid值不是int向下取整,此时right=mid-1,故返回right

20.有效的括号(easy)

"""
思路:使用栈的方法,依次遍历s,若为左括号,则入栈,若为右括号且栈不为空,则看右括号是否与栈顶的左括号匹配,匹配则返回True
"""
class Solution:
    def isValid(self, s: str) -> bool:
        matchingBrackets = {")":"(", "]":"[", "}":"{"}
        stack = []
        for i in s:
            if i in '([{':
                stack.append(i)              #左括号则入栈
            elif i in ')]}':
                if stack == []:            
                    return False
                else:
                    if matchingBrackets[i] == stack[-1]:    #若右括号与栈顶左括号匹配
                        stack.pop()                         #栈顶左括号出栈
                    else:
                        return False
        if stack == []:               #遍历完后,栈为空则全部匹配成功
            return True
        else:
            return False
225. 用队列实现栈(easy)

class MyStack:
    def __init__(self):
        self.queue1 = collections.deque()
        self.queue2 = collections.deque()

    def push(self, x: int) -> None:
        self.queue2.append(x)
        while self.queue1:
            self.queue2.append(self.queue1.popleft())
        self.queue1, self.queue2 = self.queue2, self.queue1

    def pop(self) -> int:
        return self.queue1.popleft()

    def top(self) -> int:
        return self.queue1[0]

    def empty(self) -> bool:
        return not self.queue1
739.每日温度(medium)

在这里插入图片描述

"""
单调栈思路:我们实际上就是要找到每个数右边第一个比它大的数
从左到右依次遍历温度,让数组的下标入栈(注意是下标不是温度!)
比较栈顶元素所在位置的温度与当前的温度,若当前温度更低,则温度对应的下标入栈;若当前温度更高,则栈顶元素出栈,数组中填入当前温度与栈顶温度的间隔天数
"""
class Solution:
    def dailyTemperatures(self, temperatures: List[int]) -> List[int]:
        stack = [0]
        answer = [0]*len(temperatures)
        for i in range(1,len(temperatures)):
            if temperatures[i] <= temperatures[stack[-1]]:     #当前温度小于栈顶温度
                stack.append(i)              #入栈
            else:
                while len(stack) != 0 and temperatures[i] > temperatures[stack[-1]]:                   #栈不为空且当前温度大于栈顶温度
                    answer[stack[-1]] = i - stack[-1]       
                    stack.pop()            #出栈
                stack.append(i)            #当前温度下标入栈
        return answer

二叉树

104.二叉树的最大深度(easy)

在这里插入图片描述

# Definition for a binary tree node.
# class TreeNode:
#     def __init__(self, val=0, left=None, right=None):
#         self.val = val
#         self.left = left
#         self.right = right
class Solution:
    def maxDepth(self, root: TreeNode) -> int:
        if not root:
            return 0
        else:
            left_height = self.maxDepth(root.left)
            right_height = self.maxDepth(root.right)
        return max(left_height,right_height) + 1
226.翻转二叉树(easy)

在这里插入图片描述

# Definition for a binary tree node.
# class TreeNode:
#     def __init__(self, val=0, left=None, right=None):
#         self.val = val
#         self.left = left
#         self.right = right
class Solution:
    def invertTree(self, root: TreeNode) -> TreeNode:
        if not root:
            return root
        left = self.invertTree(root.left)
        right = self.invertTree(root.right)
        root.left,root.right = right,left
        return root
617.合并二叉树(easy)

在这里插入图片描述
在这里插入图片描述

# Definition for a binary tree node.
# class TreeNode:
#     def __init__(self, val=0, left=None, right=None):
#         self.val = val
#         self.left = left
#         self.right = right
class Solution:
    def mergeTrees(self, t1: TreeNode, t2: TreeNode) -> TreeNode:
        if not t1:
            return t2
        if not t2:
            return t1
        merged = TreeNode(t1.val+t2.val)
        merged.left = self.mergeTrees(t1.left,t2.left)
        merged.right = self.mergeTrees(t1.right,t2.right)
        return merged
101.对称二叉树(easy)

在这里插入图片描述

# Definition for a binary tree node.
# class TreeNode:
#     def __init__(self, val=0, left=None, right=None):
#         self.val = val
#         self.left = left
#         self.right = right
"""
t1,t2只要有一个为空,则返回False
t1,t2都为空,则返回True
采用递归的思想,判断左右子树是否镜像对称,直到有true或false
"""
class Solution:
    def isSymmetric(self, root: TreeNode) -> bool:
        def tree(t1,t2):
            if not t1 and not t2:
                return True
            elif not t1 or not t2:
                return False
            elif t1.val != t2.val:
                return False
            else:
             #判断t1左子树与t2右子树是否是镜像对称的,t1右子树与t2左子树是否是镜像对称的
                return tree(t1.left,t2.right) and tree(t1.right,t2.left)    
        #判断根的左右子树是否是镜像对称的
        return tree(root.left,root.right)
110.平衡二叉树(easy)

在这里插入图片描述

class Solution:
    def isBalanced(self, root: TreeNode) -> bool:
        """
        思路:递归地去遍历每个节点,计算每个节点地左右子树的深度,判断左右子树的深度是否会超过1,若不超过1则返回True,否则返回False
        """
        #求树的深度
        def depth(root):
            if not root:
                return 0
            left = depth(root.left)
            right = depth(root.right)
            return max(left,right) + 1
        #求每个节点左右子树的深度差
        def compare_depth(root):
            if not root:      #若为空树则左右子树均为空
                return True
            #左右子树的深度,调用求深度的递归函数
            leftdepth = depth(root.left)    
            rightdepth = depth(root.right)
            if abs(leftdepth - rightdepth) > 1:
                return False
            #否则,深度差小于1,再递归地找左右子树的子树看其是否平衡
            return compare_depth(root.left) and compare_depth(root.right)
        return compare_depth(root)

数学问题

326. 3的幂(easy)
  1. 2的幂
  2. 4的幂同理
    在这里插入图片描述
"""
思路:n一直除以3,直到n=1则该数是3的幂
"""
class Solution:
    def isPowerOfThree(self, n: int) -> bool:
        #试除法
        while n and n % 3 == 0:     
            n = n / 3
        if n==1:
            return True
        return False
#递归法 
class Solution:
    def isPowerOfThree(self, n: int) -> bool:
        if n <= 0:
            return False
        if n == 1:
            return True
        if n % 3 != 0:
            return False       

        return self.isPowerOfThree(n/3)
202.快乐数(easy)

在这里插入图片描述

#本题还可使用快慢指针以及哈希表方法求解
class Solution:
    def isHappy(self, n: int) -> bool:
        def calculate_happy(num):
            sum_ = 0
            while num:
                sum_ += (num % 10) ** 2    #从个位开始依次取,平方求和
                num  = num // 10
            return sum_
        record = []                   #记录中间结果
        while True:
            n = calculate_happy(n)    #将n赋值为位置平方和
            if n == 1:
                return True
            elif n in record:        #若中间结果重复出现说明陷入死循环,不是快乐数
                return False
            else:
                record.append(n)
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值