算法学习之路(二)

1、最长公共前缀

编写一个函数来查找字符串数组中的最长公共前缀。

如果不存在公共前缀,返回空字符串 ""。

示例 1:

输入:strs = ["flower","flow","flight"]
输出:"fl"
示例 2:

输入:strs = ["dog","racecar","car"]
输出:""
解释:输入不存在公共前缀。

#
class Solution:
    def longestCommonPrefix(self, strs: list[str]) -> str:
        constr = strs[0]
        if constr == '':
            return ''
        for i in range(1,len(strs)):
            if strs[i] == '':
                return ''
            if len(constr) > len(strs[i]):
                constr = constr[:len(strs[i])]
            else:
                strs[i] = strs[i][:len(constr)]
            j = len(constr)-1
            while j>=0:
                if strs[i][j] != constr[j]:
                    constr = constr[:j]
                j -= 1             
                if len(constr) <= 0:
                    return ''  
        return constr


if __name__ == '__main__':
    strs = ["flower","flow","flight"]
    solu = Solution()
    print(solu.longestCommonPrefix(strs))
#动态规划类问题,此题从尾部开始

2、删除链表中的节点

请编写一个函数,用于 删除单链表中某个特定节点 。在设计函数时需要注意,你无法访问链表的头节点 head ,只能直接访问 要被删除的节点 。

题目数据保证需要删除的节点 不是末尾节点 。

示例 1:
输入:head = [4,5,1,9], node = 5
输出:[4,1,9]
解释:指定链表中值为 5 的第二个节点,那么在调用了你的函数之后,该链表应变为 4 -> 1 -> 9
示例 2:
输入:head = [4,5,1,9], node = 1
输出:[4,5,9]
解释:指定链表中值为 1 的第三个节点,那么在调用了你的函数之后,该链表应变为 4 -> 5 -> 9
示例 3:

输入:head = [1,2,3,4], node = 3
输出:[1,2,4]
示例 4:

输入:head = [0,1], node = 0
输出:[1]
示例 5:

输入:head = [-3,5,-99], node = -3
输出:[5,-99]

#其实实际上就是利用后面节点覆盖前一节点的思想
class Solution:
    def deleteNode(self, node):

        node.val = node.next.val
        node.next = node.next.next

3、两数相加

给你两个 非空 的链表,表示两个非负的整数。它们每位数字都是按照逆序的方式存储的,并且每个节点只能存储一位数字。请你将两个数相加,并以相同形式返回一个表示和的链表。

你可以假设除了数字 0 之外,这两个数都不会以 0 开头。

示例 1:
输入:l1 = [2,4,3], l2 = [5,6,4]
输出:[7,0,8]
解释:342 + 465 = 807.
示例 2:

输入:l1 = [0], l2 = [0]
输出:[0]
示例 3:

输入:l1 = [9,9,9,9,9,9,9], l2 = [9,9,9,9]
输出:[8,9,9,9,0,0,0,1]

#
class Solution:
    def addTwoNumbers(self, l1: ListNode, l2: ListNode) -> ListNode:

        Res = p = ListNode(0)  # Res和p当前都指在表头
        temp = 0  # temp用于进位,初始为0,表示无进位,为1,则进一位
        while l1 or l2:  # 判断l1和l2是否为空,不为空,则继续
            # 将l1 和l2表长改成一样长,空的地方用0补充
            if not l1:  # 此时l1空,l2不空,则将l1增加一位,值为0
                l1 = ListNode(0)
            if not l2:  # 此时l2空,l1不空,则将l2增加一位,值为0
                l2 = ListNode(0)
            sum = l1.val + l2.val + temp  # sum表示当前节点下l1,l2,和进位值相加的结果 <10则不进位,temp置零,p链表下一节点值就是sum;>10则进位,temp置1,p链表下一节点值就是sum%10
            # print(sum)
            if (sum < 10):
                temp = 0
                p.next = ListNode(sum)
            else:
                temp = 1
                p.next = ListNode(sum % 10)
            # 当前节点运算结束,前往下一节点
            p = p.next
            l1 = l1.next
            l2 = l2.next
        if (temp):  # 判断最后一次运算有无进位,有进位,则p再加一位节点,置1
            p.next = ListNode(temp)
        return Res.next


if __name__ == '__main__':
    l1 = [2,4,3]
    l2 = [5,6,4]
    solu = Solution()
    print(solu.addTwoNumbers(l1,l2))

4、重复的子字符串

给定一个非空的字符串 s ,检查是否可以通过由它的一个子串重复多次构成。

示例 1:

输入: s = "abab"
输出: true
解释: 可由子串 "ab" 重复两次构成。
示例 2:

输入: s = "aba"
输出: false
示例 3:

输入: s = "abcabcabcabc"
输出: true
解释: 可由子串 "abc" 重复四次构成。 (或子串 "abcabc" 重复两次构成。)

#方法一:
class Solution:
    def repeatedSubstringPattern(self, s: str) -> bool:
        return s in (s+s)[1:-1]

#方法二:KMP
class Solution:
    def repeatedSubstringPattern(self, s: str) -> bool:
        n = len(s)
        next = [-1] * n
        for i in range(1,n):
            j = next[i-1]
            while j >= 0 and s[j+1] != s[i]:
                j = next[j]
            if s[j+1] == s[i]:
                next[i] = j + 1
        return next[-1] >= 0 and n % (n - 1 - next[-1]) == 0
#对于一个重复的字符串,譬如a b a b a b a b a b
#他的next数组是(我这个next数组存的是数组的元素的index)-1 -1 0 1 2 3 4 5 6 7
#观察到,除了第一个子字符串,其他子字符串的的next数组是连续的,n为长度减去next[-1] + 1就是一个##子字符串的长度n % 以上 == 0, 即成功验证

5、合并两个有序链表

将两个升序链表合并为一个新的 升序 链表并返回。新链表是通过拼接给定的两个链表的所有节点组成的。 

示例 1:
输入:l1 = [1,2,4], l2 = [1,3,4]
输出:[1,1,2,3,4,4]
示例 2:

输入:l1 = [], l2 = []
输出:[]
示例 3:

输入:l1 = [], l2 = [0]
输出:[0]

#
class Solution:
    def mergeTwoLists(self, list1: Optional[ListNode], list2: Optional[ListNode]) -> Optional[ListNode]:
        temp = 0
        if list1 == "" and list2 == "":
            return None
        elif list1 == "":
            return list2
        elif list2 == "":
            return list1
        else:
            new_list: list[int] = []
            if list1.val <= list2.val:
                new_list.append(list1.val)
                temp = list1
                temp.next = list1.next
                return temp
            else:
                new_list.append(list2.val)
                temp = list2
                temp.next = list2.next
                return temp

6、二叉树的最大深度

给定一个二叉树,找出其最大深度。

二叉树的深度为根节点到最远叶子节点的最长路径上的节点数。

说明: 叶子节点是指没有子节点的节点。

示例:
给定二叉树 [3,9,20,null,null,15,7],

    3
   / \
  9  20
    /  \
   15   7
返回它的最大深度 3 。

class Solution:
    def maxDepth(self, root: Optional[TreeNode]) -> int:
        if not root:
            return 0
        new_num = max(self.maxDepth(root.left), self.maxDepth(root.right))
        return new_num + 1

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值