Leecode 101刷题笔记之第三章:和你一起你轻松刷题(Python)

简介: 本文是关于LeetCode算法题的刷题笔记,主要介绍了使用双指针技术解决的一系列算法问题,包括Two Sum II、Merge Sorted Array、Linked List Cycle II等,并提供了详细的题解和Python代码实现。

167. Two Sum II - Input array is sorted (Easy)-Two Sum

题目描述
在一个增序的整数数组里找到两个数,使它们的和为给定值。已知有且只有一对解。
输入输出样例
输入是一个数组(numbers)和一个给定值(target)。输出是两个数的位置,从1 开始计数。

Input: numbers = [2,7,11,15], target = 9
Output: [1,2]

在这个样例中,第一个数字(2)和第二个数字(7)的和等于给定值(9)。
题解
因为数组已经排好序,我们可以采用方向相反的双指针来寻找这两个数字,一个初始指向最
小的元素,即数组最左边,向右遍历;一个初始指向最大的元素,即数组最右边,向左遍历。

如果两个指针指向元素的和等于给定值,那么它们就是我们要的结果。如果两个指针指向元
素的和小于给定值,我们把左边的指针右移一位,使得当前的和增加一点。如果两个指针指向元
素的和大于给定值,我们把右边的指针左移一位,使得当前的和减少一点。

可以证明,对于排好序且有解的数组,双指针一定能遍历到最优解。证明方法如下:假设最
优解的两个数的位置分别是l 和r。我们假设在左指针在l 左边的时候,右指针已经移动到了r;
此时两个指针指向值的和小于给定值,因此左指针会一直右移直到到达l。同理,如果我们假设
在右指针在r 右边的时候,左指针已经移动到了l;此时两个指针指向值的和大于给定值,因此
右指针会一直左移直到到达r。所以双指针在任何时候都不可能处于¹l; rº 之间,又因为不满足条
件时指针必须移动一个,所以最终一定会收敛在l 和r。
具体代码

# leetcode submit region begin(Prohibit modification and deletion)
"""
执行耗时:20 ms,击败了75.58% 的Python用户
内存消耗:13.1 MB,击败了89.31% 的Python用户
"""
class Solution(object):
    def twoSum(self, numbers, target):
        """
        :type numbers: List[int]
        :type target: int
        :rtype: List[int]
        """
        if numbers:
            start = 0
            end = len(numbers) - 1
            while start < end:
                if numbers[start] + numbers[end] == target:
                    return [start + 1, end + 1]
                elif numbers[start] + numbers[end] > target:
                    end -= 1
                else:
                    start += 1
# leetcode submit region end(Prohibit modification and deletion)

88. Merge Sorted Array (Easy)–归并有序数组

题目描述
给定两个有序数组,把两个数组合并为一个。
输入输出样例
输入是两个数组和它们分别的长度m 和n。其中第一个数组的长度被延长至m + n,多出的
n 位被0 填补。题目要求把第二个数组归并到第一个数组上,不需要开辟额外空间。

Input: nums1 = [1,2,3,0,0,0], m = 3, nums2 = [2,5,6], n = 3
Output: nums1 = [1,2,2,3,5,6]

题解
因为这两个数组已经排好序,我们可以把两个指针分别放在两个数组的末尾,即nums1 的
m 􀀀 1 位和nums2 的n 􀀀 1 位。每次将较大的那个数字复制到nums1 的后边,然后向前移动一位。
因为我们也要定位nums1 的末尾,所以我们还需要第三个指针,以便复制。

在以下的代码里,我们直接利用m 和n 当作两个数组的指针,再额外创立一个pos 指针,起
始位置为m+n􀀀1。每次向前移动m 或n 的时候,也要向前移动pos。这里需要注意,如果nums1
的数字已经复制完,不要忘记把nums2 的数字继续复制;如果nums2 的数字已经复制完,剩余
nums1 的数字不需要改变,因为它们已经被排好序。
具体代码

"""
执行用时:8 ms, 在所有 Python 提交中击败了99.61%的用户
内存消耗:12.7 MB, 在所有 Python 提交中击败了99.49%的用户
"""
def merge(nums1, m, nums2, n):
    # l为nums1的m开始索引, r为nums2的n开始索引,index为修改nums1的开始索引,然后从nums1末尾开始往前遍历
    l=m-1
    r=n-1
    index=len(nums1)-1
    # 按从大到小,从后往前修改nums1的值,每次都赋值为nums1和nums2的当前索引的较大值,然后移动索引
    while l>=0 and r>=0:
        # 通过nums2的值慢慢赋值给nums1
        if nums1[l]>nums2[r]:
            nums1[index]=nums1[l]
            l-=1
        else:
            nums1[index]=nums2[r]
            r-=1
        index-=1
    # 如果nums2还没遍历完
    while r>=0:
        nums1[index]=nums2[r]
        r-=1
        index-=1
    return nums1

142. Linked List Cycle II (Medium)-快慢指针

题目描述
给定一个链表,如果有环路,找出环路的开始点。
输入输出样例

题解
对于链表找环路的问题,有一个通用的解法——快慢指针(Floyd 判圈法)。给定两个指针,
分别命名为slow 和fast,起始位置在链表的开头。每次fast 前进两步,slow 前进一步。如果fast
可以走到尽头,那么说明没有环路;如果fast 可以无限走下去,那么说明一定有环路,且一定存
在一个时刻slow 和fast 相遇。当slow 和fast 第一次相遇时,我们将fast 重新移动到链表开头,并
让slow 和fast 每次都前进一步。当slow 和fast 第二次相遇时,相遇的节点即为环路的开始点。
具体代码

"""
执行用时:32 ms, 在所有 Python 提交中击败了84.83%的用户
内存消耗:18.9 MB, 在所有 Python 提交中击败了93.97%的用户
"""
def detectCycle(head):
    """
    :type head: ListNode
    :rtype: ListNode
    """
    if not head:return None
    slowp=fastp=head
    while fastp and fastp.next:
        slowp=slowp.next
        fastp=fastp.next.next
        if fastp and slowp==fastp:
            slowp=head
            while fastp!=slowp:
                slowp=slowp.next
                fastp=fastp.next
            return slowp
    return None

76. MinimumWindow Substring (Hard)-滑动窗口

题目描述
给定两个字符串S 和T,求S 中包含T 所有字符的最短连续子字符串的长度,同时要求时间
复杂度不得超过O(n).
输入输出样例
输入是两个字符串S 和T,输出是一个S 字符串的子串。

Input: S = "ADOBECODEBANC", T = "ABC"
Output: "BANC"

在这个样例中,S 中同时包含一个A、一个B、一个C 的最短子字符串是“BANC”。
题解
本题使用滑动窗口求解,即两个指针l 和r 都是从最左端向最右端移动,且l 的位置一定在
r 的左边或重合。注意本题虽然在for 循环里出现了一个while 循环,但是因为while 循环负责移
动l 指针,且l 只会从左到右移动一次,因此总时间复杂度仍然是O¹nº。本题使用了长度为128
的数组来映射字符,也可以用哈希表替代;其中chars 表示目前每个字符缺少的数量,flag 表示
每个字符是否在T 中存在。
具体代码

"""
执行用时:468 ms, 在所有 Python 提交中击败了5.62%的用户
内存消耗:16.1 MB, 在所有 Python 提交中击败了18.54%的用户
"""
from collections import Counter
def minWindow(s, t):
    def check(dic):
        return all(map(lambda x:x>=0,dic.values()))
    len_t,len_s=len(t),len(s)
    if len_t>len_s :return ''
    if s=='' and t=='': return ''

    a,b=Counter(),Counter(t)
    l,mans,mins=0,float('inf'),float('-inf')
    a.subtract(b)
    for r in range(len(s)):
        a[s[r]]+=1
        while check(a):
            # 说明找到更小的区间了
            if mans-mins>r-l:
                mins,mans=l,r
            a[s[l]]-=1
            l+=1
    return s[mins:mans+1] if mans!=float('inf') else ''

练习-基础难度

633. Sum of Square Numbers(Easy)

Two Sum 题目的变形题之一。
题目描述
给定一个非负整数 c ,你要判断是否存在两个整数 a 和 b,使得 a2 + b2 = c 。
输入输出样例
输入:c = 5
输出:true
解释:1 * 1 + 2 * 2 = 5
题解
双指针
i 从 0 开始
j 从可取的最大数 int(math.sqrt©) 开始
total = i * i + j * j
total > c: j = j - 1,将 total 值减小
total < c: i = i + 1,将 total 值增大
total == c:返回 True
具体代码

"""
执行用时:60 ms, 在所有 Python 提交中击败了91.84%的用户
内存消耗:13.1 MB, 在所有 Python 提交中击败了40.31%的用户
"""
def judgeSquareSum(c):
    """
    :type c: int
    :rtype: bool
    """
    import math
    l=0
    r=int(math.sqrt(c))
    while r>=l:
        sums=r * r + l * l
        if sums==c:
            return True
        elif sums>c:
            r-=1
        else:
            l+=1
    return False

680. Valid Palindrome II (Easy)

Two Sum 题目的变形题之二。
题目描述
给定一个非空字符串 s,最多删除一个字符。判断是否能成为回文字符串。
输入输出样例
输入: s = “aba”
输出: true
题解
遇到第一个不同的时候,就进行判断:删左边的或删右边的
两种可能都进行下判断
c++ 没有 [::-1] 的用法,自己实现一下
时间复杂度:O(n)
空间复杂度:O(1)
具体代码

"""
执行用时:72 ms, 在所有 Python 提交中击败了82.51%的用户
内存消耗:13.6 MB, 在所有 Python 提交中击败了43.44%的用户
"""
def validPalindrome(s):
    if s == s[::-1]:
        return True
    l, r = 0, len(s) - 1
    while l < r:
        if s[l] == s[r]:
            l, r = l + 1, r - 1
        else:
            # 考虑到只能删除一个数 那么直接
            a=s[l+1:r+1]
            b=s[l:r]
            return a==a[::-1] or b==b[::-1]

524. LongestWord in Dictionary through Deleting (Medium)

归并两个有序数组的变形题。
题目描述
给你一个字符串 s 和一个字符串数组 dictionary ,找出并返回 dictionary 中最长的字符串,该字符串可以通过删除 s 中的某些字符得到。
如果答案不止一个,返回长度最长且字母序最小的字符串。如果答案不存在,则返回空字符串。
输入输出样例
输入:s = “abpcplea”, dictionary = [“ale”,“apple”,“monkey”,“plea”]
输出:“apple”
题解
先根据长度和字符串进行排序,然后通过双指针处理字符串,如果字典里面的字符子串全部都在s中,则返回字符串本身,如果不存在则返回空字符串
具体代码

"""
执行用时:440 ms, 在所有 Python 提交中击败了19.25%的用户
内存消耗:15.5 MB, 在所有 Python 提交中击败了87.70%的用户
"""
def findLongestWord(s, dictionary):
    """
    :type s: str
    :type dictionary: List[str]
    :rtype: str
    """
    def check(dict, s):
        # 双指针判断
        ld, ls = 0, 0
        while ld < len(dict) and ls < len(s):
            if dict[ld] == s[ls]:
                ld += 1  # 在里面就找目标里下一个数
            ls += 1  # 不在里面就继续遍历原字符串
            if ld == len(dict):
                return True
        return False

    # -len(x),表示字符串长度最长的排在前面,如果遇到了相同长度的字符串,则比较两个字符串的字典序
    dictionary.sort(key=lambda x: (-len(x), x))
    for dict in dictionary:
        if check(dict, s):
            return dict
    return ''

练习-进阶难度

340. Longest Substring with At Most K Distinct Characters (Hard)

由于要VIP无法进行练习。

目录
相关文章
|
1天前
|
编解码 Java 程序员
写代码还有专业的编程显示器?
写代码已经十个年头了, 一直都是习惯直接用一台Mac电脑写代码 偶尔接一个显示器, 但是可能因为公司配的显示器不怎么样, 还要接转接头 搞得桌面杂乱无章,分辨率也低,感觉屏幕还是Mac自带的看着舒服
|
3天前
|
存储 缓存 关系型数据库
MySQL事务日志-Redo Log工作原理分析
事务的隔离性和原子性分别通过锁和事务日志实现,而持久性则依赖于事务日志中的`Redo Log`。在MySQL中,`Redo Log`确保已提交事务的数据能持久保存,即使系统崩溃也能通过重做日志恢复数据。其工作原理是记录数据在内存中的更改,待事务提交时写入磁盘。此外,`Redo Log`采用简单的物理日志格式和高效的顺序IO,确保快速提交。通过不同的落盘策略,可在性能和安全性之间做出权衡。
1538 5
|
1月前
|
弹性计算 人工智能 架构师
阿里云携手Altair共拓云上工业仿真新机遇
2024年9月12日,「2024 Altair 技术大会杭州站」成功召开,阿里云弹性计算产品运营与生态负责人何川,与Altair中国技术总监赵阳在会上联合发布了最新的“云上CAE一体机”。
阿里云携手Altair共拓云上工业仿真新机遇
|
7天前
|
人工智能 Rust Java
10月更文挑战赛火热启动,坚持热爱坚持创作!
开发者社区10月更文挑战,寻找热爱技术内容创作的你,欢迎来创作!
565 22
|
3天前
|
存储 SQL 关系型数据库
彻底搞懂InnoDB的MVCC多版本并发控制
本文详细介绍了InnoDB存储引擎中的两种并发控制方法:MVCC(多版本并发控制)和LBCC(基于锁的并发控制)。MVCC通过记录版本信息和使用快照读取机制,实现了高并发下的读写操作,而LBCC则通过加锁机制控制并发访问。文章深入探讨了MVCC的工作原理,包括插入、删除、修改流程及查询过程中的快照读取机制。通过多个案例演示了不同隔离级别下MVCC的具体表现,并解释了事务ID的分配和管理方式。最后,对比了四种隔离级别的性能特点,帮助读者理解如何根据具体需求选择合适的隔离级别以优化数据库性能。
198 3
|
10天前
|
JSON 自然语言处理 数据管理
阿里云百炼产品月刊【2024年9月】
阿里云百炼产品月刊【2024年9月】,涵盖本月产品和功能发布、活动,应用实践等内容,帮助您快速了解阿里云百炼产品的最新动态。
阿里云百炼产品月刊【2024年9月】
|
10天前
|
Linux 虚拟化 开发者
一键将CentOs的yum源更换为国内阿里yum源
一键将CentOs的yum源更换为国内阿里yum源
544 5
|
22天前
|
存储 关系型数据库 分布式数据库
GraphRAG:基于PolarDB+通义千问+LangChain的知识图谱+大模型最佳实践
本文介绍了如何使用PolarDB、通义千问和LangChain搭建GraphRAG系统,结合知识图谱和向量检索提升问答质量。通过实例展示了单独使用向量检索和图检索的局限性,并通过图+向量联合搜索增强了问答准确性。PolarDB支持AGE图引擎和pgvector插件,实现图数据和向量数据的统一存储与检索,提升了RAG系统的性能和效果。
|
6天前
|
XML 安全 Java
【Maven】依赖管理,Maven仓库,Maven核心功能
【Maven】依赖管理,Maven仓库,Maven核心功能
222 3
|
9天前
|
存储 人工智能 搜索推荐
数据治理,是时候打破刻板印象了
瓴羊智能数据建设与治理产品Datapin全面升级,可演进扩展的数据架构体系为企业数据治理预留发展空间,推出敏捷版用以解决企业数据量不大但需构建数据的场景问题,基于大模型打造的DataAgent更是为企业用好数据资产提供了便利。
324 2