Daily Leetcode

本文介绍了LeetCode上的一些经典算法题,包括使用哈希解决的两数之和问题,滑动窗口在寻找无重复字符最长子串中的应用,以及通过递归和迭代方法解决的两数相加问题。同时,还探讨了如何用两个栈实现队列以及利用不同策略找寻最长回文子串。
摘要由CSDN通过智能技术生成

题1 两数之和

Leetcode题目链接-两数之和

解:哈希思想,时间复杂度O(n),空间复杂度O(n)

Class Solution:
    def twoSum(self, nums, target):
        dict = {}
        for i,item in enumerate(nums):
            if item not in dict: dict[target-item]=i
            else: return[dict[item], i]

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

Leetcode题目链接-无重复字符的最长子串

解:维护一个滑动窗口,并构建一个辅助集合收集当前窗口的全部字符,来判断是否有重复字符。

时间复杂度O(n),空间复杂度O(n)

class Solution:
    def LengthOfLongestSubstring(self, s):
        if not s: return 0

        # 记录当前窗口左端位置
        left = 0
        # 记录当前窗口长度
        cur_len = 0
        # 记录符合条件的最长窗口长度
        max_len = 0
        # 构建辅助集合
        lookup = set()

        for i in range(len(s)):
            cur_len += 1
            while s[i] in lookup:
                # 窗口左边界右滑,窗口长度缩小,更新辅助集合
                lookup.remove(s[left])
                left += 1    
                cur_len -= 1
            lookup.add(s[i])
            if max_len < cur_len: max_len = cur_len
        
        return max_len

题2 两数相加

Leetcode题目链接-两数相加

解一:递归

class Solution:
    def addTwoNumbers(self, l1, l2):
        if not l1:
            return l2
        if not l2:
            return l1
        
        l1.val += l2.val
        
        if l1.val >= 10:
            l1.next = self.addTwoNumbers(ListNode(l1.val//10), l1.next)
            l1.val %= 10
        
        l1.next = self.addTwoNumbers(l1.next, l2.next)
        
        return l1

解二:迭代

class Solution:
    def addTwoNumbers(self, l1, l2):

        # 构建一个空头指针的新链表,来存储结果
        head = p = ListNode()
        
        # 表示当前数位结果,和下一数位的值
        cur = nex = 0
        
        # 终止条件
        while l1 or l2 or nex:
            cur = nex
            
            if l1:
                cur += l1.val
                l1 = l1.next
            if l2:
                cur += l2.val
                l2 = l2.next

            nex = cur // 10
            cur = cur % 10
            
            # 插入新结点
            p.next = ListNode(cur)
            p = p.next

        return head.next

剑指题9 用两个栈实现队列

Leetcode题目链接-用两个栈实现队列

解:

class CQueue:
    def __init__(self):
        self.in_stack = []
        self.out_stack = []
    def appendTail(self, value):
        self.in_stack.append(value)

    def deleteHead(self):
        if self.out_stack: return self.out_stack.pop()
        if not self.in_stack: return -1
        while self.in_stack: self.out_stack.append(self.in_stack.pop())
        return self.out_stack.pop()

题1480 一维数组的动态和

Leetcode题目链接-一维数组的动态和

解:

class Solution:
    def runningSum(self, nums):
        for i in range(1, len(nums)):
            nums[i] += nums[i-1]
        return nums

题5 最长回文子串

Leetcode题目链接-最长回文子串

解一:Manacher. 有以下几个关键点:一是插特殊字符来统一奇偶两种情况;二是维护一个记录臂展的辅助数组;三是记录已知的回文子串到达的最远位置,目的是充分利用探索过的信息,避免重复探索;四是利用回文串的对称性

class Solution:
    # 两侧延伸求臂展
    def expand(self, s, left, right):
        while left >= 0 and right <= len(s)-1 and s[left] == s[right]:
            left -= 1
            right += 1
        return (right-left-2) // 2

    def longestPalindrome(self, s):
        # 方便统一处理
        s = '#' + '#'.join(list(s)) + '#'

        # 记录臂展数组
        arms = []

        # 记录最大回文子串
        start, end = -1, -1

        # 记录已探索的最右边界和对应的对称中心
        center, right = -1, -1

        # 遍历更新
        for i in range(len(s)):
        
            if right > i:
                # 找到i关于center的对称点
                i_mirror = 2 * center - i
                # Manacher方法的精华都在这一行里,利用了对称点的已知信息
                cur_arm = min(right-i, arms[i_mirror])

                cur_arm = self.expand(s, i-cur_arm, i+cur_arm)
            else:
                cur_arm = self.expand(s, i, i)

            # 求得当前位置i臂展后,更新需要记录的变量
            arms.append(cur_arm)
            
            if i + cur_arm > right:
                center, right = i, i + cur_arm
            if 2 * cur_arm >= end - start:
                start, end = i - cur_arm, i + cur_arm

        return s[start+1:end:2]

解二:中心扩展

class Solution:
    def expand(self, s, left, right):
        while left >= 0 and right <= len(s)-1 and s[left] == s[right]:
            left -= 1
            right += 1
        return left+1, right-1

    def longestPalindrome(self, s):
        left, right = -1, -1
        for i in range(len(s)):
            left1, right1 = self.expand(s, i, i)
            left2, right2 = self.expand(s, i, i+1)
            if right2 - left2 >= right - left:
                left, right = left2, right2
            if right1 - left1 >= right - left:
                left, right = left1, right1
        return s[left:right+1]

解三:动态规划,鸡肋解法

class Solution:
    def longestPalindrome(self, s):
        if len(s) < 2: return s

        start, end = 0, 0
        n = len(s)
        dp = [[False] * n for _ in range(n)]

        for i in range(n):
            dp[i][i] = True

        for L in range(1, n+1):
            for i in range(n):
                j = i + L - 1
                if j >= n: break
                if s[i] != s[j]: dp[i][j] = False
                else:
                    if j - i < 2: dp[i][j] = True
                    else: dp[i][j] = dp[i+1][j-1]
                if  dp[i][j] and j - i > end - start:
                    start, end = i, j
        return s[start:end+1]

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值