首页 > 编程语言 >超高频算法——双指针思想的领悟 python

超高频算法——双指针思想的领悟 python

时间:2025-01-17 16:33:06浏览次数:3  
标签:right nums python ans 领悟 数组 超高频 指针 left

目录


问题引入1

给你一个数组(按非递减顺序排列),假定为【2,4,5,6,7,9】
请你在数组中找到两个数满足:相加等于10,返回它们的值。

你是一个不知道双指针为何物的新手小白:哇!简单啊,我直接令2为第一个数不动,接着依次枚举剩下的数作为第二个数,然后check是否和为10,发现没有找到两个数和为10,那只好接着枚举4为第一个数······看起来编程根本难不倒我啊!

那有没有效率高的做法呢?我会告诉你:有的,兄弟有的

解决方案

随便选择两个数,5和9,相加大于10,那我可以说5和9中间的数与9相加也大于10。
进一步想:我选2和9发现大于10,那么可以得出9和数组中任意数相加是大于10的。
那我不妨直接在数组中删去10,say goodbye with 10
现在是【2,4,5,6,7】,我又发现:2+7<10,即2与数组任意数相加都小于10
那我也在数组中删掉2······
为什么可以删呢?因为数组是排好序的。(tips:有序就要往二分双指针上面去想)

Talk is cheap. Show me the code.

a = [2, 4, 5, 6, 7, 9]
left, right = 0, len(a) - 1
while left < right:
    sum = a[left] + a[right]
    if sum < 10:
        left += 1
    elif sum > 10:
        right -= 1
    else:
        print(a[left], a[right])
        break

# 结果是 4 6

暴力做法:找两个数相加与10比较,时间复杂度是O(n^2)
优化做法:找最小的数和最大的数相加与10比较,时间复杂度是O(n)
This is called 双指针。
双指针(Two Pointers)是一种算法技巧,常用于解决数组或链表相关的编程问题。这种方法的基本思想是使用两个指针变量遍历数据结构的不同部分,从而达到优化性能的目的。

在这里插入图片描述

那数组是无序的呢?还用说啊,sort一下不就行了,反正要输出的是数组中的元素值,不是对应的下标,时间复杂度O(nlogn)



牛刀小试


那三数之和怎么办?什么,还有高手

三数之和 https://leetcode.cn/problems/3sum/description/

经过前面的学习,O(n^3)肯定不会写出来了吧。
正解:先排序 后外层循环枚举第一个数 这样问题是不是就和刚才一样了呢 再使用 双指针

This is code

class Solution:
    def threeSum(self, nums: List[int]) -> List[List[int]]:
        nums.sort()
        ans = []
        for i in range(len(nums) - 2):
            if i > 0 and nums[i] == nums[i - 1]:
                continue
            left, right = i + 1, len(nums) - 1
            while left < right:
                sum = nums[i] + nums[left] + nums[right]
                if sum < 0:
                    left += 1
                elif sum > 0:
                    right -= 1
                else:
                    ans.append([nums[i], nums[left], nums[right]])
                    left += 1
                    while left < right and nums[left] == nums[left - 1]:
                        left += 1
                    right -= 1
                    while left < right and nums[right] == nums[right + 1]:
                        right -= 1
        return ans



问题引入2


给定一个数组a=[1,5,4,3,2,6,7,8,9,2],将其调整成:奇数在奇数位,偶数在偶数位
只能在原数组上修改你这题目,真令我欢喜

解决方案

思路:设置两个指针,分别表示奇数位指针偶数位指针
接着只看数组最后一个元素,若为奇数,则与奇数位指针所指的元素交换;
若为偶数,则与偶数位指针所指的元素交换。同时奇数位指针去往下一个位置或者偶数位指针去往下一个位置。
可以想象数组最后一个元素为邮政公司,分别往奇数和偶数家庭发邮件。


code如下(示例):

a = [1, 5, 4, 3, 2, 6, 7, 8, 9, 2]
even = 0
odd = 1
while even < len(a) and odd < len(a):
    if a[-1] % 2 == 0:
        a[even], a[-1] = a[-1], a[even]
        even += 2
    else:
        a[odd], a[-1] = a[-1], a[odd]
        odd += 2
print(a) # [2, 1, 6, 5, 4, 3, 2, 7, 8, 9]


举一反三


是到大展身手的时候了吗?直接来吧

给定一个整数数组a=[1,8,6,2,5,4,8,3,7] ,第 i 条线的两个端点是 (i, 0) 和 (i, height[i])
找出其中的两条线,使得它们与 x 轴共同构成的容器可以容纳最多的水。
返回容器可以储存的最大水量。
说明:不能倾斜容器 *这是个奇奇怪怪的说明,bushi真有人会这样想吧 *


来源:力扣(LeetCode)

过程:
初始化双指针 left,right 分列水槽左右两端;
循环收缩 直至双指针相遇时跳出;
更新面积最大值 ans ;
选择两板中的短板,向中间收一格;
返回面积最大值 ans

关键:
可容纳水的高度由两板中的 短板 决定
要矩阵面积越大,两条垂直线的距离越远,两条垂直线的最短长度也要越长。
指针每一次移动,都可以排除一个柱子


忆!悟!

亲自动手试试吧 纸上得来终觉浅,绝知此事要躬行
盛最多水的容器https://leetcode.cn/problems/container-with-most-water/description/


题解:

class Solution:
    def maxArea(self, height: List[int]) -> int:
        left, right = 0, len(height) - 1
        ans = 0
        while left < right:
            area = (right - left) * min(height[left], height[right])
            ans = max(ans, area)
            if height[left] < height[right]:
                left += 1
            else:
                right -= 1
        return ans

没有悟的小伙伴可以去看力扣官方题解哦https://leetcode.cn/problems/container-with-most-water/solutions/207215/sheng-zui-duo-shui-de-rong-qi-by-leetcode-solution/


实战演练(双指针)


最接近的三数之和 https://leetcode.cn/problems/3sum-closest/
四数之和 https://leetcode.cn/problems/4sum/
接雨水 https://leetcode.cn/problems/trapping-rain-water/description/



问题引入3


给定一个正整数数组a=[2,3,1,2,4,3],找出总和大于等于7的长度最小的子数组
返回其长度,如果不存在返回 0 。


暴力:使用两个 for 循环,一个 for 循环固定一个数字,另一个 for 循环从下一个元素开始累加,当和大于等于 7的时候终止内层循环,记录下最小长度。时间复杂度O(n^2)


思考一下:选定2,3,1,2四个数,发现sum大于7。假如再把4加进去,已知四个数和大于7,那五个数肯定和大于7——选择缩小左端点,变成3,1,2,4。发现大于7,继续缩小左端点,变成1,2,4,停止,更新答案。
接着把3加进去,发现大于7,缩小左端点,判断是否符合······
总结:
1.维护一个有条件的不定长滑动窗口;
2.右端点右移,导致窗口扩大,不满足条件;
3.左端点右移,为了缩小窗口,重新满足条件

示例code:

a = [2, 3, 1, 2, 4, 3]
n = len(a) 
left = sum = 0
ans = n  # 初始化为inf也行
for right in range(n):
    sum += a[right]
    while sum >= 7:
        ans = min(ans, right - left + 1)  # +1怎么理解,假设left和right指向同一个位置,长度应该为1
        sum -= a[left]
        left += 1
print(ans)  # 2

在这里插入图片描述

来试试吧!

长度最小的子数组 https://leetcode.cn/problems/minimum-size-subarray-sum/description/

题解:

class Solution:
    def minSubArrayLen(self, target: int, nums: List[int]) -> int:
        ans = inf
        left, sum = 0, 0
        for right in range(len(nums)):
            x = nums[right]
            sum += x
            while sum >= target:
                ans = min(ans, right - left + 1)
                sum -= nums[left]
                left += 1
        if ans <= len(nums):
            return ans
        else:
            return 0

What is 滑动窗口

滑动窗口技术(Sliding Window Technique)是一种用于解决数组或字符串中子数组或子串问题的算法设计方法。通过维护一个动态窗口来遍历整个数据结构,从而高效地找到满足特定条件的子数组或子串。

在这里插入图片描述

关键要素


核心思想是使用两个指针(通常称为左右边界或起点终点),形成一个窗口,然后根据问题需求调整窗口的大小和位置

在这里插入图片描述




实战演练(滑动窗口)


【easy】每个字符最多出现两次的最长子字符串 https://leetcode.cn/problems/maximum-length-substring-with-two-occurrences/description/
【medium】删除最短的子数组使剩余数组有序 https://leetcode.cn/problems/shortest-subarray-to-be-removed-to-make-array-sorted/description/
【hard】找出唯一性数组的中位数 https://leetcode.cn/problems/find-the-median-of-the-uniqueness-array/description/



总结

双指针:考虑两个指针处的状态,一般不考虑指针中间的区间
滑动窗口:维护窗口内的状态,更新指针位置、记录答案


好了,以上就是全部内容。大家喜欢的话可以关注博主,后续会持续更新滴

标签:right,nums,python,ans,领悟,数组,超高频,指针,left
From: https://blog.csdn.net/2401_87245677/article/details/145194334

相关文章

  • 初学者如何用 Python 写第一个爬虫?
    ......
  • 【Python】深入探讨Python中的单例模式:元类与装饰器实现方式分析与代码示例
    《PythonOpenCV从菜鸟到高手》带你进入图像处理与计算机视觉的大门!解锁Python编程的无限可能:《奇妙的Python》带你漫游代码世界单例模式(SingletonPattern)是一种常见的设计模式,它确保一个类只有一个实例,并提供一个全局访问点。在Python中,实现单例模式的方式多种多样,包括......
  • Python魔法方法深度解析:解密 __call__、__new__ 和 __del__
    《PythonOpenCV从菜鸟到高手》带你进入图像处理与计算机视觉的大门!解锁Python编程的无限可能:《奇妙的Python》带你漫游代码世界在Python中,魔法方法(MagicMethods)是一些特殊的方法,它们允许开发者定制对象的行为。这些方法前后由双下划线包围,如__init__、__str__、__call_......
  • 【金融资产组合模型进化论】4.1 对MPT+Fama-French五因子优化方案实现Backtrader量化
    目录0.承前1.汇总代码2.近4年量化回测2.1获取近4年资产组合数据2.2对近4年资产组合数据进行量化回测3.启后3.1待优化点0.承前本篇博文是对文章,链接:【金融资产组合模型进化论】4.马科维茨资产组合模型+Fama-French五因子优化方案(理论+Python实战)实现量......
  • 【华为OD-E卷 - 最大花费金额 100分(python、java、c++、js、c)】
    【华为OD-E卷-最大花费金额100分(python、java、c++、js、c)】题目双十一众多商品进行打折销售,小明想购买自己心仪的一些物品,但由于受购买资金限制,所以他决定从众多心仪商品中购买三件,而且想尽可能的花完资金。现在请你设计一个程序帮助小明计算尽可能花费的最大资金数......
  • 【华为OD-E卷 - 一种字符串压缩表示的解压 100分(python、java、c++、js、c)】
    【华为OD-E卷-一种字符串压缩表示的解压100分(python、java、c++、js、c)】题目有一种简易压缩算法:针对全部由小写英文字母组成的字符串,将其中连续超过两个相同字母的部分压缩为连续个数加该字母,其他部分保持原样不变。例如:字符串“aaabbccccd”经过压缩成为字符串“3ab......
  • 2025毕设python在线小说阅读系统程序+论文
    本系统(程序+源码+数据库+调试部署+开发环境)带论文文档1万字以上,文末可获取,系统界面在最后面。系统程序文件列表开题报告内容一、选题背景关于在线小说阅读系统的研究,现有研究主要集中在系统的基本功能实现和用户体验优化方面,如一些商业在线阅读平台的开发与改进。专门针对......
  • 【ABKing】记一次Python SSTI的内存马技术研究
    通过对PythonSSTI的技术研究,发现网上的一些Payload具有局限性,并非能直接使用,踩了一些坑,写出了自己的独创Payload0x00起因有个用户单位反馈,HW期间被攻击队打了个RCE,并且提供了攻击队的报告和防火墙的流量。正好临近年关,闲来无事,想到已经很久没有认真钻研技术了,遂开始进行研究。......
  • 12.python的bug、异常相关
    提示:12.python的bug、异常相关文章目录bugpython异常处理机制常见异常类型bug1.语法错误SyntaxError  使用了中文符号,input输入的是字符类型误用等自查表2.索引超出错误IndexError  索引超出列表范围python异常处理机制解决方案:异常处理机制,......
  • 9.python元组与集合
    提示:python元组与集合元组没有增删改查:**元组是python内置的数据结构之一,是不可变序列(无增删改操作)**不可变序列还有字符串文章目录元组元组创建元组遍历集合集合的相关操作集合间的关系集合的数学操作集合生成式小总结不可变序列:不是不能进行增删改(相对于用......