Leetcode——双指针

力扣hot100二刷——哈希、双指针、滑动窗口 第二次刷题不在idea写代码,而是直接在leetcode网站上写,“逼”自己掌握常用的函数。 阅读详情

图解双指针原理

双指针法的一个共同特征就是可以找到 一对下标,而且这对下面满足一个约束条件,那就是

  • i 和 j 都是合法的下标,即 i < n, j < n
  • i < j

然后我们希望从中找到满足题目的条件,即 A[i]与 A[j] 之间存在一个直接关系,返回下标 (i, j)(i,j)。
以 n = 8n=8 为例,这时候全部的搜索空间是:
在这里插入图片描述

每一个格子就代表这一种情况,如果使用暴力破解的话,那么整个正方形就是我们的搜索空间,那么时间复杂度就是O(n^2)。 而使用双指针的话,那么因为约束条件的限制,我们的搜索空间就成为了上三角部分,此时的时间复杂度仍然为O(n^2),要想得到 O(n)的解法,我们就需要能够一次排除多个单元格。那么我们来看看,双指针解法是如何削减搜索空间的:

  • 假设我们以167. Two Sum II - Input array is sorted为例子解释:

一开始,我们检查右上方单元格 (0, 7),即计算 A[0] 与A[7]之间的关系 ,与 target 进行比较。如果不相等的话,则要么大于 target,要么小于 target。
在这里插入图片描述
假设此时 A[0] + A[7] 小于 target。这时候,我们应该去找和更大的两个数。由于 A[7] 已经是最大的数了,其他的数跟 A[0] 相加,和只会更小。也就是说 A[0] + A[6] 、A[0] + A[5]、……、A[0] + A[1] 也都小于 target,这些都是不合要求的解,可以一次排除。这相当于 i=0i 的情况全部被排除。对应用双指针解法的代码,就是 i++,对应于搜索空间,就是削减了一行的搜索空间,如下图所示。
在这里插入图片描述
排除掉了搜索空间中的一行之后,我们再看剩余的搜索空间,仍然是倒三角形状。我们检查右上方的单元格 (1,7),计算 A[1] + A[7] 与 target 进行比较。
在这里插入图片描述

假设此时 A[0] + A[7] 大于 target。这时候,我们应该去找和更小的两个数。由于 A[1] 已经是当前搜索空间最小的数了,其他的数跟 A[7] 相加的话,和只会更大。也就是说 A[1] + A[7] 、A[2] + A[7]、……、A[6] + A[7] 也都大于 target,这些都是不合要求的解,可以一次排除。这相当于 j=0的情况全部被排除。对应用双指针解法的代码,就是 j++,对应于搜索空间,就是削减了一列的搜索空间,如下图所示。
在这里插入图片描述
可以看到,无论 A[i] + A[j] 的结果是大了还是小了,我们都可以排除掉一行或者一列的搜索空间。经过 n步以后,就能排除所有的搜索空间,检查完所有的可能性。

搜索空间的减小过程如下面动图所示:

在这里插入图片描述

引用Leetcode链接




167. Two Sum II - Input array is sorted

描述:

  • Given an array of integers that is already sorted in ascending order,find two numbers such that they add up to a specific target number.
    The function twoSum should return indices of the two numbers such that
    they add up to the target, where index1 must be less than index2.

说明:

  • Your returned answers (both index1 and index2) are not zero-based.
    You may assume that each input would have exactly one solution and you may not use the same element twice.

例子:

Input:   numbers = [2,7,11,15], target = 9
Output:    [1,2]
Explanation:    The sum of 2 and 7 is 9. Therefore index1 = 1, index2 = 2.

分析:

使用双指针,一个指针指向值较小的元素,一个指针指向值较大的元素。指向较小元素的指针从头向尾遍历,指向较大元素的指针从尾向头遍历。

  • 如果两个指针指向元素的和 sum == target,那么得到要求的结果;
  • 如果 sum > target,移动较大的元素,使 sum变小一些;
  • 如果 sum<target,移动较小的元素,使 sum 变大一些。

数组中的元素最多遍历一次,时间复杂度为O(N)。
只使用了两个额外变量,空间复杂度为 O(1)。

源码:

Java版本


class Solution {
    public int[] twoSum(int[] numbers, int target) {
        if (numbers == null) return null;
        int i = 0, j = numbers.length - 1;
        while (i < j) {
            int sum = numbers[i] + numbers[j];
            if (sum == target) {
                return new int[]{i + 1, j + 1};
            } else if (sum < target) {
                i++;
            } else {
                j--;
            }
        }
        return null;
    }
}

Python版本

class Solution:
    def twoSum(self, numbers: List[int], target: int) -> List[int]:
        i = 0
        j = len(numbers) - 1
        while i < j:
            if numbers[i] + numbers[j] == target:
                return [i+1, j+1]
            elif numbers[i] + numbers[j] > target:
                j -= 1
            else:
                i += 1



633. Sum of Square Numbers

描述:

Given a non-negative integer c, your task is to decide whether there’re two integers a and b such that a2 + b2 = c.

例子:

 Example 1:
	 Input: 5
	 Output: True
 	 Explanation: 1 * 1 + 2 * 2 = 5
 	 
 Example 2:	 
 	 Input: 3
	 Output: False

分析:

源码:

Python版本

class Solution:
    def judgeSquareSum(self, c: int) -> bool:
        b = int(c**0.5)
        a = 0
        while(a<=b):
            if a*a+b*b == c:
                return True
            elif a*a+b*b<c:
                a = a+1
            else:
                b = b-1
        return False

Java版本

class Solution {
    public boolean judgeSquareSum(int c) {
        if(c<0)return false;
        else{
            int j = (int)Math.sqrt(c); 
            int i = 0;
            while(i<=j){
                if(i*i + j*j == c) return true;
                else if (i*i + j*j < c) i++;
                else j--;
            }
            return false;
        }
    }
}

345. Reverse Vowels of a String

描述

Write a function that takes a string as input and reverse only the vowels of a string.
The vowels does not include the letter “y”.

例子

Example 1:

Input: "hello"
	Output: "holle"
	Example 2:
	
Example 1:
	Input: "leetcode"
	Output: "leotcede"

分析

Java源码

class Solution {
    private HashSet<Character> vowels  = new HashSet<Character>(){{
        add('a');
        add('e');
        add('i');
        add('o');
        add('u');
        add('A');
        add('E');
        add('I');
        add('O');
        add('U');
    }};
    public String reverseVowels(String s) {
        int i = 0;
        int j = s.length()-1;
        char sArr[] = s.toCharArray();
        while(i<j){
            while(i<j && !vowels.contains(sArr[j])){
                j--;
            }
            while(i<j && !vowels.contains(sArr[i])){
                i++;
            }
            if (sArr[i] != sArr[j]) {
                char temp = sArr[j];
                sArr[j] = sArr[i];
                sArr[i] = temp;
            }
            i++;
            j--;
        }
        return String.valueOf(sArr);

    }
}

680. 验证回文字符串 Ⅱ

描述

给定一个非空字符串 s,最多删除一个字符。判断是否能成为回文字符串。

示例:

示例 1:
	输入: "aba"
	输出: True
	
示例 2:
	输入: "abca"
	输出: True
	
解释: 你可以删除c字符。
注意:字符串只包含从 a-z 的小写字母。字符串的最大长度是50000。

分析:

我的思路有两种解法:

方法一:暴力破解法

暴力法在字符串中的大部分题目都是可以使用的,因为暴力,通用性大,但是效率及其的低下,因此也不建议使用。
首先思路就是对给定的字符串中的每个索引 i,然后每次删除一个元素之后再进行判断是否为回文数,那么总共就要判断n+1次,每次需要比较n个字符。只要有一次为回文数,那么我们将返回 true,否则返回 false。
时间复杂度:O(n^2)
空间复杂度:O(n)

方法二:双指针法

使用双指针法很容易判断一个字符串是否为回文数,因为一个指针从左往右遍历 ,一个从右往左遍历。如果两个指针指向用一个字符,那么两个指针同时向中间靠拢。
本题的难点在于可以删除一个字符,那么既可以删除左边的字符,也可以删除右遍的字符。

源码:

为改进版

class Solution {
    public boolean validPalindrome(String s) {
   		//双指针循环找出不等于的字符索引
        for(int i=0 ,j = s.length()-1;i<j;i++,j--){
            if(s.charAt(i)!= s.charAt(j)){
            	// 左边和右边删除都做一次,只要有一次为true,最终的结果都为true
                return isPalindrome(s, i, j - 1) || isPalindrome(s, i + 1, j);
            }
        }
        return true;
        
    }
    // 验证是否为回文数
    public boolean isPalindrome(String s,int i,int j){
        while(i<j){
           if(s.charAt(i)!= s.charAt(j)){
               return false;
           }else{
               i++;
               j--;
           }
        }
        return true;
    }
}

改进版

class Solution {
    public boolean validPalindrome(String s) {
        char[] chars = s.toCharArray();
        int i = 0;
        int j = chars.length - 1;
        //双指针循环找出不等于的字符索引
        while (i < j && chars[i] == chars[j]) {
            i++;
            j--;
        }
        //删除左边循环判断
        if (isValid(chars,i + 1,j)) return true;
        //删除右边循环判断
        if (isValid(chars,i,j - 1)) return true;
        //如果上面都是false,那么结果肯定是false
        return false; 
    }
    //验证是否是回文
    private boolean isValid(char[] chars,int i,int j) {
        while (i < j) {
            if (chars[i++] != chars[j--]) {
                return false;
            }
        }
        return true;
    }}

在这里插入图片描述

charAt(i)与char[i]的效率区别

@Test
    public void test1(){
        String s = "";
        for (int i = 0; i < 100000; i++) {
            s+= "*";
        }
        long start_time;

        start_time = System.nanoTime();
        System.out.println(s.charAt(6666));
        System.out.println("遍历单个charAt为:"+(System.nanoTime()-start_time));

        start_time = System.nanoTime();
        for (int i = 0; i < s.length(); i++) {
            char char1 = s.charAt(i);
        }
        System.out.println("循环遍历每一个charAt为:"+(System.nanoTime()-start_time));

        char[] chars;

        start_time = System.nanoTime();
        chars = s.toCharArray();
        System.out.println(chars[6666]);
        System.out.println("遍历单个toCharArray为:"+(System.nanoTime()-start_time));
        
        start_time = System.nanoTime();
        chars = s.toCharArray();
        for (int i = 0; i < chars.length; i++) {
            char char2 = chars[i];
        }
        System.out.println("循环遍历每一个toCharArray为:"+(System.nanoTime()-start_time));
    }

在这里插入图片描述
通过实验可以发现,char[] chars = s.toCharArray();通过一个字符数组的形式来遍历的效率要比直接用字符串的方式调用charAt()方法要快。但是内存方面都需要在底层创建一个数组,所用的内存空间大致是相同的。

多周期路径及set_multicycle_path详解 默认情况下,每条路径都被定义为单周期,即源触发器在时钟的任一边沿启动(launch)的数据都应该由目的触发器在时钟的下一上升沿捕获(capture)。 有的设计需要在数据被捕获前提供一些额外的周期,这类路径被称为多周期路径。 一、set_multicycle_path命令 命令格式如下: set_multicycle_path ......... 阅读详情

相关推荐

Qt6导入QtChart绘制图表(添加组件)

我在按照大佬们的说明添加QtChart时发现,我的电脑上并不能正确的添加QtChart并编译通过,所以在综合了两位大佬的说明又自己探索了一番后,正确编译通过,分享出来,以便同志们节省一些时间。

Nuaa0719301zyx的博客 2950

【Leetcode】5. 最长回文子串(双指针算法)

【Leetcode】5. 最长回文子串(双指针算法)

qq_44653420的博客 502

在 Ubuntu 上安装和配置 PostgreSQL 实录

本文介绍了在Ubuntu系统上安装和配置PostgreSQL数据库的完整步骤。主要内容包括:1)通过官方源或PPA源安装最新版本;2)修改配置文件(postgresql.conf和pg_hba.conf)以允许远程访问;3)设置postgres用户密码;4)创建新用户并配置权限;5)防火墙设置和重启服务;6)验证安装和远程连接方法。文章提供了详细的命令行操作指导,帮助用户完成从安装到远程访问的全部配置过程。

qq_58168857的博客 1204

一文多图讲清楚解决最长回文子串问题的【中心扩展算法】与【Manacher算法】

图解中心扩展算法、Manacher算法

weixin_54383080的博客 2074

SCI论文发表很容易【5】:比较容易中的期刊

整理了一些经管方面比较容易中稿的期刊,可供大家参考

qq_25018077的博客 1678

pandas教程:2012 Federal Election Commission Database 2012联邦选举委员会数据库

里面包含了支持者的名字,职业和雇主,地址,赞助金额。我们可以已经能想到如何切割、整理数据,来提取赞助者的统计数据,或提取宣传活动的模式,这里我们展示一些不同的分析方法。可以看到有些职业是同一种工作类型,指代的是同一个东西。这两个连续操作是分别独立执行的,一个结束后,另一个才开始。上,这里我是把数据集压缩成了ZIP格式,解压后能正常导入)。我觉得也有必要好好了解一下,这个网站做了很好的讲解,),所以我们最好添加这样的信息。这样的情况,即把两个索引操作连在一起。,发现映射关系被正常执行了,所以这里的。

Cachel Wood的博客 349

两数之和(two sum)问题通用解法(map法和双指针)

文章目录1. [LeetCode01:two sum](https://leetcode.com/problems/two-sum/)题意思路1:map法代码1:思路2:双指针解法代码2小结[LintCode607. Two Sum III - Data structure design](https://www.lintcode.com/problem/two-sum-iii-data-stru...

超级无敌小胖头 3310

Gmsh+OCC对应版本库编译

输入 GMSH_DLL_EXPORT值C:\LIB\OCCT-7_8_0-i;9、如果只是生成库文件编译gmesh工程即可生成文件在C:\LIB\Gmsh\gmsh-4.13.1-Windows64-B\Debug 下gmsh.dll、gmsh.lib、gmsh.h、gmshc.h文件;3、CMAK编译Gmsh对应OCC版本的,CMAK选择源文件路径C:\LIB\Gmsh\gmsh-4.13.1-source,生成构建文件路径C:\LIB\Gmsh\gmsh-4.13.1-Windows64-B。

u013401364的博客 411

LeetCode 例题精讲 | 04 用双指针解 Two Sum:缩减搜索空间

点击关注上方“五分钟学算法”,设为“置顶或星标”,第一时间送达干货。转自面向大象编程本期例题:LeetCode 167 - Two Sum II - Input array is sor...

程序员吴师兄的博客 729

综述性论文别再堆砌文献!用GPT-5.1 Thinking轻松攻克四大关键难点,真正实现高效高质撰写(附AI提示词)

逻辑构建上以往都是先梳理一篇文献的领域研究脉络,明确其发展阶段、核心议题等,再搭建初步的大纲,借助思维导图或者别的方式将筛选后的文献观点按主题归类到对应章节,理清楚每个章节间的递进或并列关系,最后再逐个章节进行补充过渡表述,那么做的目的其实就是摆脱文献堆砌问题。人工做法往往是对比不同文献的研究方法、数据来源与核心结论,再清晰标注每类成果的优缺点,找到文献中存在的争议焦点,找到之后再梳理争议产生的核心原因,最后在基于现有研究,推出还未被探索的研究方向,从而提炼出创新切入点。2)文献之间的相同点与不同点;

智能AI让学术科研更容易 173

大模型之Spring AI实战系列(二):Spring Boot + OpenAI 打造聊天应用全攻略

本篇文章是《Spring AI实战》专栏的第一篇开发入门文章,我们将借助一个完整的OpenAI聊天应用示例,详细介绍如何运用Spring Boot和Spring AI快速搭建一个支持OpenAI API的聊天服务,全面涵盖基础对话、流式对话、多提供商配置等核心功能。

寻道AI,探索AI无限可能! 6866

力扣(leetcode)题目总结——双指针篇

本系列文章初衷是为了按类别整理出力扣(leetcode)最经典题目,一共100多道题,每道题都给出了非常详细的解题思路、算法步骤、代码实现。因为力扣题目顺序是随机的,并没有按照算法分类,导致同一类型的算法强化训练不够。所以本系列文章就是来帮你完成算法分类,针对每种算法做强化训练,保证让你以后遇到题目直接秒杀。本篇文章主要是针对双指针相关的算法题,一次性帮你搞定所有双指针题!

weixin_46571171的博客 1637

Statistics and Machine Learning Toolbox

Statistics and Machine Learning Toolbox(带书签),MATLAB统计学习工具

力扣(leetcode)hot 100双指针看这一篇就够了

这里是阳明Coding,给大家分享一下力扣hot100里面关于双指针的题目的一些解决方法及思路。如果有其他想法或者思路。我也会顺嘴提一下。

yyyCode的博客 1524

WINCC7.3破解文件

WINCC7.3硬件够破解文件,有需要的下载!WINCC7.3硬件够破解文件,有需要的下载!

复分析 阿尔福斯(Ahlfors) 第三版答案 英文

答案分为十章,有部分习题没有答案,全英文复分析阿尔福斯(Ahlfors) 第三版答案

力扣数组与双指针题目精选(将双指针运用到极致)

精选力扣中可以使用双指针解法的题目,增强对于双指针的灵活运用

2301_78179333的博客 195

力扣数组之双指针

双指针就是在纸上画多个指针,然后推演,比如快慢指针,前后指针等等!!!外加一个index存放新数组的下标。

2301_78138281的博客 1183

力扣刷题总结之双指针

双指针思想 双指针,指的是在遍历对象的过程中,不是普通的使用单个指针进行访问,而是使用两个相同方向(快慢指针)或者相反方向(对撞指针)的指针进行扫描,从而达到相应的目的 。 双指针是很多算法的基础,如归并排序、滑动窗口、字符匹配(左右括号匹配)等。滑动窗口即维持一段区间。 在很多情况下,双指针能帮助我们找到空间或是时间复杂度更低的解。比单个指针来回移动的效率从o(n2)提高到o(n)。 算法框架 ...

ComeOnMr博客 750

【双指针】双指针算法详解两道经典OJ【力扣27,力扣26,力扣38】超详细算法教程

【双指针】双指针算法详解两道经典OJ【力扣27,力扣26,力扣38】超详细算法教程 今天又又到了我们刷力扣题的时间啦! 今天博主给大家带来的三道题是: 27. 移除元素 26. 删除有序数组中的重复项 88. 合并两个有序数组 这三道题,都是双指针算法题的一个入门题,掌握这三道题,认识双指针算法,是我们今天的目标! 文章目录前言OJ27 移除元素题目描述算法分析实现代码OJ26 删除有序数组中的重复项题目描述算法分析实现代码OJ88 合并两个有序数组题目描述算法分析实现代码尾声 前言 那么这里博主先安利一

系统编程、网络编程 986

Leetcode力扣常考高频题-双指针

考察频率由两部分组成: Leetcode100题 面试考察频率(https://codetop.cc/#/home)表格中默认超过30次即为高频题 题号 难度 题目描述 解法 考察频率 11 中等 能装最多水的容器 双指针 Leetcode100 15 中等

luy0710的博客 225

【力扣LeetCode热题h100】哈希、双指针、滑动窗口

本文总结了力扣LeetCode热题H100中关于哈希、双指针和滑动窗口的解题方法。主要内容包括: 两数之和问题:介绍了暴力解法(O(n²))、排序+双指针法(O(nlogn))和哈希表法(O(n))三种解决方案,比较了不同方法的时间复杂度。 字母异位词分组:通过将字符串排序作为哈希表的键,将异位词分组,时间复杂度为O(nklogk)。 最长连续序列:讨论了排序后遍历的解法(O(nlogn)),并提示存在更优的O(n)解法。 文章着重分析了各算法的复杂度,并提供了C++和Java的实现代码,强调哈希表在解决这

qq_41725967的博客 711

LeetCode算法(双指针)

今天的题目主要都是力扣前100中,关于双指针的题。

jiangyule的博客 1076

【LeetCode】【力扣刷题】三数之和 双指针操作

完结

weixin_43766021的博客 208

双指针-202.快乐数-力扣(LeetCode)

我们可以知道int的最大值为2.1x10^9,我们取9999999999,这比int大的多了,这时它的平方数为9^2x10=810,所以我们得到了一个范围及int产生的平方数的范围【1,810】,当经历811次操作后,根据鸽巢原理,必然会出现一个相同的数,即会出现循环)= fast,为了避免赋值时slow和fast值相同导致不能进入循环,我们可以让fast指向下一个平方数,为了方便计算平方数,我们需要自己实现一个函数去计算平方数。我们能发现平方数是不断更新的,所以我们可以用平方数的值用于做双指针。

black_bear_white的博客 533

【算法专题】双指针算法之18. 四数之和(力扣)

🏆本篇主题为:【算法专题】双指针算法之18. 四数之和(力扣)

cilmy23的note 1298

力扣热题100——双指针

这种区间里求面积的题目,对撞指针是常用的做法(就是左右两个指针)。我们设置左右两个指针分别扫描数组,对于扫到的区间计算面积,然后现在该移动哪个指针呢?因为更大的那一边可能还会参与更大的容器的构成,所以不能移动!这道题的关键是我们要明白,如果一个柱子的左右两边有比它更高的柱子,我们设置左边比它高的柱子的最大值为。那么我们假设这个数组是有序的(从小到大排序),那么我们就可以利用两个指针从前后扫描来枚举!和盛水最多的容器一样,这种区间求面机的题目,常常可以用对撞指针来求解(这道题也可以有其他解法)

qq_45769627的博客 1149

力扣100题解及笔记 双指针

双指针法的主要优点是高效性,通常能够将问题的时间复杂度降低到线性(O(n))或线性对数(O(n log n))

hiahiakk的博客 1026
上一篇: 基于paramiko实现SSH的连接问题
下一篇: Java读取配置文件
Dim_Jerry
博客等级 码龄8年 14粉丝 50原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值