Leetcode的刷题小记录

2020.5.21 最长回文子串

在这里插入图片描述
学习了动态规划(dp)算法,这个算法本质上是一个递归的算法,只要是递归就要注意递归的截止条件,动态规划中要会列状态转移方程。
本题中:寻找最长回文子串,如果要用递归的思想,则先从最简单的回文串开始考虑:
回文串length = 1时,它肯定是回文串
回文串length = 2时,要判断s[0]和s[1]是不是相等的,才能判断是否是回文串
递归:回文串长度 >2时,则先判断头尾元素是否相等,如果相等,则去掉头尾,继续判断这个子回文串

递归终止条件:去掉头尾后,长度为0
动态规划本质上就是这个递归思想,只不过递归的过程用状态转移方程来描述:
dp[i][j] = dp[i+1][j-1]
dp[i][j]就是s[i:j](左闭右闭)是否是回文串,因此要调整一下递归的终止条件,不能让dp[i+1][j-1] 变得奇奇怪怪
最后,对于每一个回文串,记录长度和index即可,本题leetcode通过。

class Solution:
    def longestPalindrome( self, s: str) -> str:

        max_len = 1
        start = 0
        length = len(s)
        if length <2:
            return s
        dp = [[False ]*length for _ in range(length) ]
        for i in range(length):
            dp[i][i] = True # 第i个元素自己本身是回文数
        for j in range(1,length):
            for i in range(0,j):
                if s[i] == s[j]:
                    if j - i <3 :
                        dp[i][j] = True
                    else:
                        dp[i][j] = dp[i+1][j-1] #状态转移方程
                else:
                    dp[i][j] = False
                    
                if dp[i][j]:
                    cur_len = j-i+1
                    if cur_len > max_len:
                        max_len = cur_len
                        start = i
                        
        return s[start:start+max_len]

2020.5.22 从前序遍历,中序遍历中构造二叉树

在这里插入图片描述
这一题也是应用了递归的思想,对于二叉树的题,递归很方便,而能用递归的思想就是别把问题看的太复杂。比如
前序遍历 preorder = [3,9,20,15,7]
中序遍历 inorder = [9,3,15,20,7]
注意到前序遍历顺序“根左右”,中序遍历顺序“左根右”,因此就应该看成
前序遍历preorder = [3,9,20,15,7]
中序遍历 inorder = [9,3,15,20,7]
这样就很清晰了,代码leetcode通过

# Definition for a binary tree node.
# class TreeNode:
#     def __init__(self, x):
#         self.val = x
#         self.left = None
#         self.right = None

class Solution:
    def buildTree(self, preorder: List[int], inorder: List[int]) -> TreeNode:
        if not preorder or not inorder :
            return None
        root = TreeNode(preorder[0])
        idx = inorder.index(preorder[0])
        root.left = self.buildTree(preorder[1:1+idx],inorder[:idx])
        root.right = self.buildTree(preorder[1+idx:],inorder[idx+1:])


        return root

2020.5.23 最小覆盖子串

在这里插入图片描述
从这道题中学习到了一种滑动窗口的方法,也就是双指针。
原理:一开始两个指针指向头,右指针往右走,边走边检查是不是识别到了子串,也就是不断增加窗口长度的过程。当右指针走到一个位置,他是s的子串时,此时要记录头尾索引长度等信息来作为判断。之后左指针开始往右走,窗口长度开始减小,只要他还满足子串要求,则就应该继续记录信息。一直到他不是子串了,窗口就不能继续变小,而是应该增大了。这个窗口就在这滑动过程中变大变小,最短位置的信息也就在其中被记录了。

此外,子串判断这里应该是要用字典的,但是我不会,只好自己构造了一个Map类,他的作用就是一个键值对映射,用来记录元素以及元素出现次数。代码leetcode通过用例267/268,最后一个巨长通过不了,超时了

class Map:
    def __init__(self):
        self.val = []
        self.count = []
    def add(self,string):
        for str1 in string:
            if str1 not in self.val:
                self.val.append(str1)
                self.count.append(1)
            else:
                idx = self.val.index(str1)
                self.count[idx] += 1
    def is_sub(self,cutmap):
        for i in self.val:
            if i not in cutmap.val:
                return False 
            tidx = self.val.index(i)
            cidx = cutmap.val.index(i)
            if self.count[tidx] > cutmap.count[cidx]:                
                return False
        return True
def t_in_cut(cut,t):
    if len(t) > len(cut):
        return False
    tmap= Map()
    tmap.add(t)
    cutmap = Map()
    cutmap.add(cut)
    if tmap.is_sub(cutmap):
        return True
    else:
        return False
class Solution:   
    def minWindow(self,s: str, t: str) -> str:
        left = 0
        right = 1
        length = float('inf')
        idx_start = 0
        idx_end = 0
        count = 0
        cut = s[left:right]
        for right in range(1,len(s)+1):
            cut = s[left:right]
            while t_in_cut(cut,t):
                cut = s[left:right]
                cur_length = right - left
                if cur_length < length:
                    length = cur_length
                    idx_start = left 
                    idx_end = right
                left += 1
        return(s[idx_start - 1:idx_end])

2020.5.24 两数相加

在这里插入图片描述
看题目描述觉得很简单,实际上逻辑判断起来还是蛮头大的,也可能是我对链表运用得不熟悉吧。
我的思路是:链表中两个数相加,首先判断链表长度是不是一样的,其次判断有没有进位,也就是判断两次,有2*2 = 4 种情况。
长度一样,有进位:进位计数器置1,创造下一节点;
长度一样,无进位:进位计数器置0,如果后面还有长度一样的,创造下一节点;
长度不一样,有进位:进位计数器置1,创造下一节点;
长度不一样,无进位:进位计数器置0,如果后面还有l1或l2,创造下一节点

# Definition for singly-linked list.
# class ListNode:
#     def __init__(self, x):
#         self.val = x
#         self.next = None

class Solution:
    def addTwoNumbers(self, l1: ListNode, l2: ListNode) -> ListNode:               
        head = res = ListNode(0)
        c = 0
        #如果数位是对齐的
        while l1 !=None and l2 !=None:
            #判断是否进位
            if l1.val +l2.val +c <=9:
                res.val = l1.val +l2.val +res.val
                c = 0
                #没进位,再判断是否要创建新元素
                if l1.next !=None and l2.next !=None:
                    out = res.next = ListNode(0)
                    res = out
            #进位了肯定有新元素
            else:
                res.val = l1.val +l2.val -10 +res.val
                out = res.next = ListNode(1)
                res = out
                c =1
            l1,l2 = l1.next,l2.next
        #如果数位没对齐
        while l1 !=None:
            if c == 0:
                out = res.next = ListNode(l1.val)
                res = out
            else:
                if res.val + l1.val  <10:
                    res.val = res.val + l1.val 
                    c = 0
                else:
                    res.val = res.val + l1.val -10
                    out = res.next = ListNode(1)
                    res = out
                    c = 1
            l1 = l1.next
        while l2 !=None:
            if c == 0:
                out = res.next = ListNode(l2.val)
                res = out
            else:
                if res.val + l2.val <10:
                    res.val = res.val + l2.val
                    c = 0
                else:
                    res.val = res.val + l2.val -10
                    out = res.next = ListNode(1)
                    res = out
                    c = 1
            l2 = l2.next
        return head

2020.5.25 LRU缓存机制

在这里插入图片描述
手撸字典解决,leetcode通过

class LRUCache:
    def __init__(self, capacity: int):
        self.keylist = []
        self.vallist = []
        self.capacity = capacity

    def get(self, key: int) -> int:
        if key in self.keylist:
            idx = self.keylist.index(key)
            self.keylist.append(self.keylist[idx])
            self.vallist.append(self.vallist[idx])
            del self.keylist[idx]
            del self.vallist[idx]
            return self.vallist[len(self.vallist)-1]
        else:
            return -1

    def put(self, key: int, value: int) -> None:

        if key in self.keylist:
            idx = self.keylist.index(key)
            self.vallist[idx] = value
            self.keylist.append(self.keylist[idx])
            self.vallist.append(self.vallist[idx])
            del self.keylist[idx]
            del self.vallist[idx]
        else:
            if len(self.keylist) >= self.capacity:
                del self.keylist[0]
                del self.vallist[0]
            self.keylist.append(key)
            self.vallist.append(value)

2020.5.27 可被K整除的子数组

在这里插入图片描述
一开始的直接思路是暴力求解,用两层for循环遍历所有子数组,用sum求数组的和,这样时间复杂度就是O(n3),直接不通过了
看了题解,学到了一种用哈希表解题的,时间复杂度居然只有O(n),不过感觉还不是太理解,先贴代码,看看过几天还记不记得

class Solution:
    def subarraysDivByK(self, A: List[int], K: int) -> int:
        #暴力遍历所有可能的子数组,不通过
        """
        count = 0
        if A
        for i in range(len(A)):
            for j in range(i+1,len(A)+1):
                cut = A[i:j]
                if sum(cut)%K == 0:
                    count +=1
        return count
        """
        res = {0:1}
        total,out = 0,0
        for val in A:
            total += val
            modres = total%K
            same =res.get(modres,0)
            out += same
            res[modres] = same + 1
        return out 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值