【刷题记录】

跟随代码随想录https://programmercarl.com/的刷题记录
1.15

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

class Solution(object):
    def evalRPN(self, tokens):
        """
        :type tokens: List[str]
        :rtype: int
        """
        arr = []
        while tokens:
            if len(tokens)!=0:
                arr.append(tokens.pop(0))
            if arr[len(arr)-1] =='/' or arr[len(arr)-1]=='*' or arr[len(arr)-1]=='+' or arr[len(arr)-1]=='-':
                key=str(arr[len(arr)-3])+str(arr[len(arr)-1])+str(arr[len(arr)-2]) #匹配到运算符则将运算符和前面两个合成为一个字符串
                arr.pop()
                arr.pop()
                arr.pop()	#并删除最后三个
                arr.append(int(eval(key)))	#算出结果后添加进数组
        return int(arr[0])

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

class Solution:
    def isValid(self, s: str):
        sta =[]

        for i in s:
            if i== '(':
                sta.append(')')
            elif i == '[':
                sta.append(']')
            elif i == '{':
                sta.append('}')
            elif len(sta) == 0 or sta[-1] != i:  # 如果sta空了说明右括号有多 或者不匹配,直接返回false
                return False
            else:
                sta.pop() #括号匹配成功,弹出最后一位
        return True if not sta else False  #循环结束如果sta内还有内容,说明左括号有多,则返回false

数组,模拟过程
在这里插入图片描述
在这里插入图片描述

class Solution:
    def generateMatrix(self, n):
        arr=[[0]*n]*n
        for i in range(len(arr)): #创建n*n的矩阵
            arr[i]=arr[i]*1
        num=1
        left, right, up, down = 0, n - 1, 0, n - 1
        while left<right and up <down:
            for x in range(left,right):
                arr[up][x]=num
                num+=1
            for y in range(up,down):
                arr[y][right]=num
                num+=1
            for x in range(right,left,-1):
                arr[down][x]=num
                num+=1
            for y in range(down,up,-1):
                arr[y][left]=num
                num+=1
            left+=1	#开始缩小范围,直到left>right 和 up >down 退出循环
            up+=1
            right-=1
            down-=1
        if n%2==1:	#如果n为奇数,在中间补上数字
            arr[n//2][n//2]=num
        return arr

1.16
二叉树
三种深度遍历

# 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 preorderTraversal(self, root: Optional[TreeNode]) -> List[int]:
        nums=[]
        def a(head):
            if not head:
                return
            nums.append(head.val)
            a(head.left)
            a(head.right)
        a(root)
        return nums


'''先序,遍历'''
# 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 preorderTraversal(self, root: Optional[TreeNode]) -> List[int]:
        arr=[]
        if root: 
            nums=[root]
            while nums:
                head=nums.pop()
                arr.append(head.val)
                if head.right is not None:
                    nums.append(head.right)
                if head.left is not None:
                    nums.append(head.left)
        return arr

'''中序,迭代'''
# Definition for a binary tree node.
# class TreeNode(object):
#     def __init__(self, val=0, left=None, right=None):
#         self.val = val
#         self.left = left
#         self.right = right
class Solution(object):
    def inorderTraversal(self, root):
        """
        :type root: TreeNode
        :rtype: List[int]
        """
        arr1=[]
        
        if root is None:
            return None
        arr=[]
        while len(arr)!=0 or root is not None:
            if root is not None:
                arr.append(root)
                root=root.left
            else:
                 root=arr.pop()
                 arr1.append(root.val)
                 root=root.right               
        return arr1
'''中序,递归'''
# Definition for a binary tree node.
# class TreeNode(object):
#     def __init__(self, val=0, left=None, right=None):
#         self.val = val
#         self.left = left
#         self.right = right
class Solution(object):
    def inorderTraversal(self, root):
        """
        :type root: TreeNode
        :rtype: List[int]
        """
        arr1=[]
        def a(head):
            if head is None:
                return
            a(head.left)
            arr1.append(head.val)
            a(head.right)
        a(root)
        return arr1
'''后序.递归'''
# 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 postorderTraversal(self, root: Optional[TreeNode]) -> List[int]:
        arr1=[]
        def a(head):
            if head is None:
                return
            a(head.left)
            a(head.right)
            arr1.append(head.val)

        a(root)
        return arr1
        
'''后序,迭代'''
# 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 postorderTraversal(self, root: Optional[TreeNode]) -> List[int]:
        arr=[]
        arr1=[]
        if root: 
            nums=[root]
            while nums:
                head=nums.pop()
                arr.append(head.val)
                if head.left is not None:	
                    nums.append(head.left)                
                if head.right is not None:
                    nums.append(head.right)

        for i in arr[::-1]:
            arr1.append(i)
        return arr1

前序遍历:中左右
中序遍历:左中右
后序遍历:左右中
所以后序遍历只要把前序遍历左右互换后倒过来就行

1.17
二叉树层序遍历(广度)
在这里插入图片描述

# 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 levelOrderBottom(self, root: TreeNode) -> List[List[int]]:
        nums=[] 	#每一层数据
        nums1=[]	#总数据
        if root:
            que=[root]	#头节点入栈
            while que:
                for _ in range(len(que)):
                    q=que.pop(0)	#先进的先出
                    if q:
                    '''节点不为空将节点数据加入数组,并且如果左右数据不为空按照左-右的顺序压入栈'''
                        nums.append(q.val)	
                        if q.left:
                            que.append(q.left)	
                        if q.right:
                            que.append(q.right)
                nums1.append(list(nums)) #保存数据
                nums=[]					#初始化每一层的数据
        return list(reversed(nums1))	#按照题目要求反转列表

在这里插入图片描述
这题只要根据上题,层次遍历完后输出每层数据最后一个就行

class Solution:
    def rightSideView(self, root: TreeNode) -> List[int]:
        # Definition for a binary tree node.
        nums=[]
        nums1=[]
        if root:
            que=[root]
            while que:
                for _ in range(len(que)):
                    q=que.pop(0)
                    if q:
                        nums.append(q.val)
                        if q.left:
                            que.append(q.left)
                        if q.right:
                            que.append(q.right)
                nums1.append(nums[-1])
                nums=[]
        return nums1

在这里插入图片描述
这题和上题类似
将 nums1.append(nums[-1]) 改为 nums1.append(sum(nums)/len(nums))
pass

在这里插入图片描述
类似,nums1.append(nums[-1])—>nums1.append(max(nums)))
pass

在这里插入图片描述

"""
# Definition for a Node.
class Node:
    def __init__(self, val: int = 0, left: 'Node' = None, right: 'Node' = None, next: 'Node' = None):
        self.val = val
        self.left = left
        self.right = right
        self.next = next
"""

class Solution:
    def connect(self, root: 'Optional[Node]') -> 'Optional[Node]':
        if root:
            que=[root]	
            while que:
                n=len(que)
                for i in range(n):
                    head=que.pop(0)	
                    if head.left:
                        que.append(head.left)
                    if head.right:
                        que.append(head.right)
                    if i==n-1:
                        break
                    head.next=que[0]  
        return root

多叉树的层次遍历
在这里插入图片描述

# 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 levelOrder(self, root):
        nums = []
        num = []

        if not root:
            return nums
        q = [root]
        while q:
            for _ in range(len(q)):
                cur = q.pop(0)
                num.append(q.val)
                if cur.children:
                    q.append(cur.children)
            nums.append(num)
            num = []
        return nums

1.18

在这里插入图片描述

'''排列组合出所有可能,最后去重,再干掉所有不合法的
方法和思路是对的
但由于Permutations,全排列的时间复杂度(O(n*n!)
所以这个我自己想的简单粗暴的方法百分百超时
'''
class Solution:
    def generateParenthesis(self, n):
        strs=["(",')']*n
        from itertools import permutations
        kh=list(set(list(permutations(strs,n*2))))
        s=[]
        def ishf(s):	#前面造的轮子,直接拿过来用了
            sta =[]
            for i in s:
                if i== '(':
                    sta.append(')')
                elif len(sta) == 0 or sta[-1] != i:
                    return False
                else:
                    sta.pop()
            return True if not sta else False
        for i in kh:
            if ishf(i):
                s.append(''.join(i))
        return s

在这里插入图片描述

1.19
在这里插入图片描述

# 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: Optional[TreeNode]) -> int:
        cot=0
        if root:
            nums=[root]
            
            while nums:
                for i in range(len(nums)):
                    num=nums.pop(0)
                    if num:
                        if num.left:
                            nums.append(num.left)
                        if num.right:
                            nums.append(num.right)
                cot+=1
        return cot

在这里插入图片描述
上一题只要跑完层序遍历后返回一共循环多少次就行
这题检测到当左右节点都为空时就返回

非递归
# 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 minDepth(self, root: TreeNode) -> int:
        if root == None:
            return 0

        que = [(root,1)]  //设置根节点
        while que:
            cur, depth = que.pop(0)
            
            if cur.left == None and cur.right == None:
                return depth
            #先左子节点,由于左子节点没有孩子,则就是这一层了
            if cur.left:
                que.append((cur.left,depth + 1))
            if cur.right:
                que.append((cur.right,depth + 1))
        return 0

二叉树翻转
在这里插入图片描述
前序遍历或者后序遍历都行,边遍历边交换

# 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 None
        root.left,root.right=root.right,root.left //交换
        self.invertTree(root.left)				//左
        self.invertTree(root.right)				//return root

1.20
了解一下回溯算法
个人理解的回溯算法是,这一步走不通,就返回去走另一步,直到走完所有可能,有点像二叉树的遍历,走到最低端,返回上一步,走另一边,直到走完所有节点,回溯的本质是穷举,穷举所有可能,然后选出我们想要的答案
回溯是递归的副产品,只要有递归就会有回溯。

在这里插入图片描述

class Solution:
    def combine(self, n: int, k: int) -> List[List[int]]:
        nums1=[]
        nums2=[]

        def vd(startnum):
            if len(nums2)==k:	//终止条件
                nums1.append(list(nums2))
                return
            for i in range(startnum,n+1)://宽度遍历
                nums2.append(i)
                vd(i+1)					//深度遍历
                nums2.pop()	//删除这步,走另一步,回溯算法
        vd(1)
        return nums1

因为有for循环最后pop的存在,所有每一次for遍历都可以看作nums2没有加任何东西,重新开始遍历,每一次递归nums2内都会多一个数,直到满足条件跳出递归

在这里插入图片描述

在这里插入图片描述

class Solution:
    def combinationSum3(self, k: int, n: int) -> List[List[int]]:
        nums1=[]
        nums2=[]
        def vd(start):
            if sum(nums2)==n and len(nums2)==k:		//因为这题要满足两个条件,所有只有两个条件同时满足才返回
                nums1.append(list(nums2))
                return
            if len(nums2)==k or sum(nums2)>=n:		//如果只满足一个条件,那么另外一个条件不可能满足,直接返回
                return
            for i in range(start,10):
                nums2.append(i)
                vd(i+1)
                nums2.pop()
        vd(1)
        return nums1

1.21
在这里插入图片描述

class Solution:
    def combinationSum(self, candidates: List[int], target: int) -> List[List[int]]:
        nums=[]
        nums1=[]
        def vd(start):
            if sum(nums1)==target:
                nums.append(list(nums1))
                return
            if sum(nums1)>target:
                return
            for i in range(start,len(candidates)):
                nums1.append(candidates[i])
                vd(i)	//可以重复选取,所以不需要+1
                nums1.pop()	//回溯
        vd(0)
        return nums
      

在这里插入图片描述
比起上题,需要去重,

class Solution:
    def combinationSum2(self, candidates: List[int], target: int) -> List[List[int]]:
        nums=[]
        nums1=[]
        candidates.sort()

        def vd(start):
            if sum(nums1)==target:
                nums.append(list(nums1))
                return
            if sum(nums1)>target:
                return
            for i in range(start,len(candidates)):
                nums1.append(candidates[i])
                if  i > start and candidates[i] in candidates[0:i]:#遇到重复的跳过一轮循环
                    continue
                vd(i+1)
                nums1.pop()
        vd(0)
        
        return nums

1.22

在这里插入图片描述
分割问题,和组合问题类似,组合问题选取了一个以后,下一个就要从这个数的下一个开始选取,分割问题割出一段后,再割出下一段就要从剩下的第一个开始

class Solution:
    def partition(self, s):
        strs=[]
        strs1=[]
        def vd(start):
            if start >= len(s):	#字符串被切完后返回
                strs.append(list(strs1))
                return
            for i in range(start,len(s)):
                temp = s[start:i + 1]  #切割字符串
                if temp == temp[::-1]:  # 判断回文串,若反序和正序相同,意味着这是回文串
                    strs1.append(temp)
                    vd(i + 1)  #从切割后的下一处继续切割,直到字符串被切完
                    strs1.pop()
                else:
                    continue
        vd(0)
        return strs

在这里插入图片描述
这题主要是三个点号的位置,分段的数字大小都要是0~255之间,且不能含有前导零,所以需要一个判断是否是有效数段的

class Solution:
    def restoreIpAddresses(self, s):
        nums_ip=[]
        point=0		#点号数量,如果有三个点号说明分割完成
        def isva(s,start,end):	#判断是否满足三个条件
            if start > end:
                return False
            if s[start] == '0' and start != end:
                return False
            if not 0 <= int(s[start:end+1]) <= 255:
                return False
            return True
        def vd(s,start,point):
            if point==3:	#递归结束条件
                if isva(s,start,len(s)-1):
                    nums_ip.append(s[:])
                return
            for i in range(start,len(s)):
                if isva(s,start,i):
                    s=s[:i+1]+'.'+s[i+1:]	#添加点号
                    vd(s,i+2,point+1)	#因为存在点号,所以每次起始位置都要+2,每次递归都新增一个点号
                    s = s[:i + 1] + s[i + 2:]	#删除点号,回溯
                else:
                    break
        vd(s,0,point)
        return nums_ip

在这里插入图片描述
子集数量就是从0到数组长度每个数多少的组合,

class Solution:
    def subsets(self, nums: list):
        nums1 = []
        nums2 = []

        def vd(start,k):
            if len(nums2)==k:
                nums1.append(list(nums2))
                return
            for i in range(start,len(nums)):
                nums2.append(nums[i])
                vd(i + 1,k)
                nums2.pop()
        for i in range(len(nums)+1):#从0开始遍历到数组长度,i的个数的组合全部加进列表任何返回就行
            vd(0,i)
        return nums1

1.23
在这里插入图片描述
直接导入itertools包,一步解决
在这里插入图片描述
pass
全排列,不放回有序组合,只要每一次都从头开始选就行,由于从头开始选会选到重复的,所以遇到重复的直接跳过就行

在这里插入代码片
class Solution:
    def permute(self, nums: List[int]) -> List[List[int]]:
        nums1 = []
        nums2 = []

        def vd():
            if len(nums2)==len(nums):
                nums1.append(list(nums2))
                return
            for i in range(len(nums)):
                if nums[i] in nums2:	#如果已经出现过,则跳过本层循环
                    continue 
                nums2.append(nums[i])
                vd()
                nums2.pop()
        vd()
        return nums1

回溯算是学到了点皮毛,年后再去刷hard题
复习一下链表
在这里插入图片描述

# Definition for singly-linked list.
# class ListNode:
#     def __init__(self, val=0, next=None):
#         self.val = val
#         self.next = next
class Solution:
    def removeElements(self, head: ListNode, val: int) -> ListNode:
        head = ListNode(next=head) 
        cur = head
        while cur.next:
            if cur.next.val == val:
                cur.next = cur.next.next #让cur.next直接指向下一个节点,删除cur.next节点
            else:
                cur = cur.next
        return head.next

在这里插入图片描述

class Node:
    def __init__(self, val):#节点
        self.val = val
        self.next = None


class MyLinkedList:
    def __init__(self, head):
        self.head = head

    def get(self, index: int) -> int:
        cur = self.head
        if cur:
            return -1
        cot = 0
        while cot != index:
            if cur.next is None:
                return -1
            cur = cur.next
            cot += 1

        return cot

    def addAtHead(self, val: int) -> None:
        node = Node(val)
        node.next = self.head	#将头节点向下移动
        self.head = node		#添加到头节点

    def addAtTail(self, val: int) -> None:
        node = Node(val)
        if self.head is None:
            self.head = Node
        else:
            cur = self.head
            while cur.next:	#遍历到尾部
                cur = cur.next
            cur.next = node #添加进尾部

    def addAtIndex(self, index: int, val: int) -> None:
        cot = 0
        node = Node(val)
        if index <= 0:
            self.addAtHead(val)
        else:
            cur = self.head
            if cur is None:
                self.head = node
                return
            while cot != index-1:	

                cur = cur.next
                cot += 1
                if cur.next is None:
                    return
            node.next = cur.next
            cur.next = node

    def deleteAtIndex(self, index: int) -> None:
        cot = 0
        cur = self.head
        while cot != index-1:
            if cur.next is None:
                return
            cur = cur.next
            cot += 1
        cur.next=cur.next.next 

写这种老长老长的题目真折磨人,链表自己试过,都能完成功能,但是不知道这种题应该怎么提交,点提交就报错

1.25

在这里插入图片描述

class Solution:
    def lowestCommonAncestor(self, root: 'TreeNode', p: 'TreeNode', q: 'TreeNode') -> 'TreeNode':
        if not root or root == p or root == q:	#如果找到了 节点p或者q,或者遇到空节点,就返回
            return root
       
        left = self.lowestCommonAncestor(root.left, p, q)	#后序遍历,最先处理的一定是叶子节点
        right = self.lowestCommonAncestor(root.right, p, q)
        
        if left and right: 	#遇到空节点直接返回
            return root
        if left:	
            return left
        return right

在这里插入图片描述
和层序遍历一样,只要统计最后的个数就行

class Solution:
    def countNodes(self, root: TreeNode) -> int:
        nums=[]
        nums1=[]
        if root:
            que=[root]
            while que:
                for _ in range(len(que)):
                    q=que.pop(0)
                    if q:
                        nums.append(q.val)
                        if q.left:
                            que.append(q.left)
                        if q.right:
                            que.append(q.right)
                
                nums1.append(nums)
                nums=[]
        else : return
        sum_=[]
        for i in nums1:
            sum_.append(len(i))
        return sum(sum_)	
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值