优选算法合集————双指针(专题一)

news2024/12/23 0:39:48

题目一:移动零

题目描述:

给定一个数组 nums,编写一个函数将所有 0 移动到数组的末尾,同时保持非零元素的相对顺序。

请注意 ,必须在不复制数组的情况下原地对数组进行操作。

示例 1:

输入: nums = [0,1,0,3,12]
输出: [1,3,12,0,0]

示例 2:

输入: nums = [0]
输出: [0]
题目解析:

本题要求我们,在不移动数组的情况下,将数组内所有的0元素移动到末尾,且其他元素不能改变,我们可以创建两个指针,让一个指针去遍历数组,一个指针等待着交换,我们使用数组下标来代替指针。

算法思路:

1,让cur遍历数组,元素为0的时候,cur++;

2,当cur遇到非零的元素,dest++;并且与cur进行交换,cur++;

3,直到cur下标等于arr.length,循环结束。

代码实现:
class Solution {
    public void moveZeroes(int[] nums) {
        int cur = 0;
        int dest = -1;
        int tmp;
        while(cur<nums.length){
            if(nums[cur]==0){
                cur++;
            }else{
                dest++;
                tmp = nums[cur];
                nums[cur] = nums[dest];
                nums[dest] = tmp;
                cur++;
            }
        }
    }

}

题目二:覆写零

题目描述:

给你一个长度固定的整数数组 arr ,请你将该数组中出现的每个零都复写一遍,并将其余的元素向右平移。

注意:请不要在超过该数组长度的位置写入元素。请对输入的数组 就地 进行上述修改,不要从函数返回任何东西。

示例 1:

输入:arr = [1,0,2,3,0,4,5,0]
输出:[1,0,0,2,3,0,0,4]
解释:调用函数后,输入的数组将被修改为:[1,0,0,2,3,0,0,4]

示例 2:

输入:arr = [1,2,3]
输出:[1,2,3]
解释:调用函数后,输入的数组将被修改为:[1,2,3]
题目解析:

题目的意思就是我们遍例数组的时候,如果遇到0,我们就要打印两遍0,如果是其他的,打印一次,但不能超过数组原有的长度,我们还是定义两个指针。

算法思路:

1,定义指针dest,cur,先让cur,dest,模拟遍历一次数组,dest下标为arr,length时停止,记录下cur的位置,

2,如果开始dest在n下标,cur下标对应的数为0,让arr[n-1]=0,dest-=2,cur-=1;

3,从cur下标开始往前遍历,让dest重写我们的数组。

代码实现:
class Solution {
    public void duplicateZeros(int[] arr) {
        int dest = -1;
        int cur = 0;
        int s = arr.length;
        while(dest<s-1){
            if(arr[cur]==0){
                dest+=2;
            }
            else{
                dest++;
            }
            cur++;
        }
        cur--;
        if(dest==s){
            arr[s-1] = 0;
            dest-=2;
            cur--;
        }

        while(cur>=0){
            if(arr[cur]==0){
                arr[dest]=0;
                dest--;
                arr[dest]=0;
                dest--;
                cur--;
            }else{
                arr[dest]=arr[cur];
                dest--;
                cur--;
            }
        }
    }
}

题目三:快乐数

题目描述:

编写一个算法来判断一个数 n 是不是快乐数。

「快乐数」 定义为:

  • 对于一个正整数,每一次将该数替换为它每个位置上的数字的平方和。
  • 然后重复这个过程直到这个数变为 1,也可能是 无限循环 但始终变不到 1。
  • 如果这个过程 结果为 1,那么这个数就是快乐数。

如果 n 是 快乐数 就返回 true ;不是,则返回 false 。

示例 1:

输入:n = 19
输出:true
解释:
12 + 92 = 82
82 + 22 = 68
62 + 82 = 100
12 + 02 + 02 = 1

示例 2:

输入:n = 2
输出:false
题目解析:

题会给到一个整数,整数的每个位上的数可以拆开进行平方,如果这个数一直进行这个操作,直到得数为1时,它就是快乐数,这题我们该怎么写呢,大家有没有做过环形链表求入口点的,

我们可以把这道题想像成链表求交点,利用快慢指针,快指针变化两次,慢指针变化一次,这里的变化指的就是把数拆开求平方,直到相遇,看看相遇点是不是1,(我们所能填入的数是一定会相遇的,这里不讲原理了) 

算法思路:

快慢指针,求交点

 代码实现:
class Solution {
    public int change(int n){
        int num = 0;
        int a = 0;
        while(n!=0){
            a = n%10;
            num+=a*a;
            n/=10;
        }
        return num;
    }
    public boolean isHappy(int n) {
        int fast = change(n);
        int slow = n;
        while(fast!=slow){
            fast = change(change(fast));
            slow = change(slow);
        }
        if(fast==1){
            return true;
        }
        return false;
    }
}

题目四:盛水最多的容器

题目描述:

给定一个长度为 n 的整数数组 height 。有 n 条垂线,第 i 条线的两个端点是 (i, 0) 和 (i, height[i]) 。

找出其中的两条线,使得它们与 x 轴共同构成的容器可以容纳最多的水。

返回容器可以储存的最大水量。

说明:你不能倾斜容器。

示例 1:

输入:[1,8,6,2,5,4,8,3,7]
输出:49 
解释:图中垂直线代表输入数组 [1,8,6,2,5,4,8,3,7]。在此情况下,容器能够容纳水(表示为蓝色部分)的最大值为 49。

示例 2:

输入:height = [1,1]
输出:1
题目解析:

数组下标可以看作我们的长,数组下标的值可以当做高,并且高只计算最短边,让我们找到最大的容积,我们可以使用暴力枚举,不用想,绝对会超时,这时我们可以想想排序,单调性,二分等等,找这道题有没有规律。

因为高我们看的是小的高,先看cur,无论我们怎么选另一边的高,高也只能为1,所以我们这时只要关注长就行了。

算法思路:

1,cur与dest下标的值进行比较,小下标的h*(dest-cur)为每次的容积;小下标移动

2,直到cur==dest;

3,比较求出的最大值;

代码实现:
class Solution {
    public int maxArea(int[] height) {
        int cur = 0;
        int dest = height.length-1;
        int max = 0;
        while(cur<dest){
            if(height[cur]<=height[dest]){
                int a = 0;
                a = height[cur]*(dest-cur);
                if(a>=max) max = a;
                cur++;
            }else{
                int a = 0;
                a = height[dest]*(dest-cur);
                if(a>=max) max = a;
                dest--;
            }
        }
        return max;
    }
}

题目五:有效三角形的个数

题目描述:

给定一个包含非负整数的数组 nums ,返回其中可以组成三角形三条边的三元组个数。

示例 1:

输入: nums = [2,2,3,4]
输出: 3
解释:有效的组合是: 
2,3,4 (使用第一个 2)
2,3,4 (使用第二个 2)
2,2,3

示例 2:

输入: nums = [4,2,3,4]
输出: 4

提示:

  • 1 <= nums.length <= 1000
  • 0 <= nums[i] <= 1000
题目解析: 

我们在给的一组数据中挑选3个符合三角形构成规则的数,我们依旧可以使用暴力枚举,3层循环,不用想绝对超时,我们知道三角形是两边之和大于第三边,转化为编程条件就是a+b>c,b+c>a,a+c>b;这里我们可以使用一个小技巧,就是当a<b<c的时候,我们只需要判断a+b>c就行了,因为那两个条件在a<b<c时是一定成立的,我们可以尝试排序数组,再利用单调性解决问题。

算法思路: 

1,给数组排序,固定一个大数c

2,数组0下标a,c-1为b,利用单调性双指针判断a+b与c的关系

3,利用单调性移动a和b的下标。

代码实现:
class Solution {
    public int triangleNumber(int[] nums) {
        int c = nums.length-1;
        int a = 0;
        int b = c-1;
        int count = 0;
        Arrays.sort(nums);
        for(;c>=2;c--){
            a = 0; b = c-1;
            while(a<b){
                if(nums[a]+nums[b]>nums[c]){
                    count += (b-a);
                    b--;
                }else{
                    a++;
                }
            }
        }
        return count;
    }
}

题目六:和为s的两个数字

题目描述:

给定一个整数数组 nums 和一个整数目标值 target,请你在该数组中找出 和为目标值 target  的那 两个 整数,并返回它们的数组下标。

你可以假设每种输入只会对应一个答案,并且你不能使用两次相同的元素。

你可以按任意顺序返回答案。

示例 1:

输入:nums = [2,7,11,15], target = 9
输出:[0,1]
解释:因为 nums[0] + nums[1] == 9 ,返回 [0, 1] 。

示例 2:

输入:nums = [3,2,4], target = 6
输出:[1,2]

示例 3:

输入:nums = [3,3], target = 6
输出:[0,1]
题目解析:

这到题是让我们在数组中找到一组数,让他俩的和为target,这到题之前是递增的数组,我们就可以使用双指针,单调性来做,但是现在改了,不有序了,我们只能使用哈希表来做了,大家当一个知识扩展吧。

 算法思路:

1,创建哈希表,遍历数组

2,查询数组中是否存在targert-nums[i];如果存在返回下标

3,不存在将元素put到哈希表中。

代码实现: 
class Solution {
    public int[] twoSum(int[] nums, int target) {
        HashMap<Integer,Integer> hashMap = new HashMap<>();
        for(int i=0;i<nums.length;i++){
            if(hashMap.containsKey(target-nums[i])){
                return new int[]{hashMap.get(target-nums[i]),i};
            }
            hashMap.put(nums[i],i);
        }
        return new int[0];
    }
}

题目七:三数之和

题目描述:

给你一个整数数组 nums ,判断是否存在三元组 [nums[i], nums[j], nums[k]] 满足 i != ji != k 且 j != k ,同时还满足 nums[i] + nums[j] + nums[k] == 0 。请你返回所有和为 0 且不重复的三元组。

注意:答案中不可以包含重复的三元组。

示例 1:

输入:nums = [-1,0,1,2,-1,-4]
输出:[[-1,-1,2],[-1,0,1]]
解释:
nums[0] + nums[1] + nums[2] = (-1) + 0 + 1 = 0 。
nums[1] + nums[2] + nums[4] = 0 + 1 + (-1) = 0 。
nums[0] + nums[3] + nums[4] = (-1) + 2 + (-1) = 0 。
不同的三元组是 [-1,0,1] 和 [-1,-1,2] 。
注意,输出的顺序和三元组的顺序并不重要。

示例 2:

输入:nums = [0,1,1]
输出:[]
解释:唯一可能的三元组和不为 0 。

示例 3:

输入:nums = [0,0,0]
输出:[[0,0,0]]
解释:唯一可能的三元组和为 0 。
题目解析: 

要在题目给的数组中挑出3个不重复的元素让他们相加为0,我们在找到所有元素后还要进行去重操作,我们可以使用暴力枚举也就是三层循环,绝对超时,我们使用了暴力枚举,想找规律,排序,单调性,双指针,二分等等办法,

算法思路: 

1,固定一个数a,让letf=a+1,right=arr.length-1;

2,利用单调性判断left和right的移动方向;

3,让a从头开始直到n-1;

class Solution {
    public List<List<Integer>> threeSum(int[] nums) {
        int a = 0;
        int left = 0;
        int right = 0;
        int n = nums.length;
        Arrays.sort(nums);
        int target = 0;
        List<List<Integer>> list1 = new LinkedList<>();
        for(;a<n;){
            left = a+1; right = n-1; target = -nums[a];
            while(left<right){
                if(nums[left]+nums[right]<target){
                    left++;
                }else if(nums[left]+nums[right]>target){
                    right--;
                }else{
                    List<Integer> list2 = new LinkedList<>();
                    list2.add(nums[a]);
                    list2.add(nums[left]);
                    list2.add(nums[right]);
                    list1.add(list2);
                    left++;
                    right--;
                    while(left<right && nums[left]==nums[left-1]) left++;
                    while(left<right && nums[right]==nums[right+1]) right--;
                }
            }
            a++;
            while(a<n && nums[a]==nums[a-1]) a++;
        }
        return list1;
    }
}
 扩展题型:

给你一个由 n 个整数组成的数组 nums ,和一个目标值 target 。请你找出并返回满足下述全部条件且不重复的四元组 [nums[a], nums[b], nums[c], nums[d]] (若两个四元组元素一一对应,则认为两个四元组重复):

  • 0 <= a, b, c, d < n
  • abc 和 d 互不相同
  • nums[a] + nums[b] + nums[c] + nums[d] == target

你可以按 任意顺序 返回答案 。

示例 1:

输入:nums = [1,0,-1,0,-2,2], target = 0
输出:[[-2,-1,1,2],[-2,0,0,2],[-1,0,0,1]]

示例 2:

输入:nums = [2,2,2,2,2], target = 8
输出:[[2,2,2,2]]

思路是一样的;

class Solution {
    public List<List<Integer>> fourSum(int[] nums, int target) {
        List<List<Integer>> list1 = new LinkedList<>();
        Arrays.sort(nums);
        int a = 0;
        int b = 0;
        int left = 0;
        int right = 0;
        int n = nums.length;
        long target2 = 0;
        for(;a<n;){
            b = a+1;
            target2 = (long)target-(long)nums[a]; 
            for(;b<n;){
                left = b+1; right = n-1;
                while(left<right){
                    if(nums[left]+nums[right]<target2-nums[b]){
                        left++;
                    }else if(nums[left]+nums[right]>target2-nums[b]){
                        right--;
                    }else{
                        List<Integer> list2 = new LinkedList<>();
                        list2.add(nums[a]);
                        list2.add(nums[b]);
                        list2.add(nums[left]);
                        list2.add(nums[right]);
                        list1.add(list2);
                        left++;
                        right--;
                        while(left<right && nums[left]==nums[left-1]) left++;
                        while(left<right && nums[right]==nums[right+1]) right--;
                    }
                }
                b++;
                while(b<n && nums[b]==nums[b-1]) b++;
            }
            a++;
            while(a<n && nums[a]==nums[a-1]) a++;
        }
        return list1;
    }
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2238654.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

python基于深度学习的音乐推荐方法研究系统

需求设计 一款好的音乐推荐系统其目的是为用户进行合理的音乐推荐&#xff0c;普通的用户在登录到系统之后&#xff0c;能够通过搜索的方式获取与输入内容相关的音乐推荐&#xff0c;而以管理员登录到系统之后&#xff0c;则可以进行徐昂管的数据管理等内容操作。此次的需求主…

Docker 镜像和容器的导入导出及常用命令

Docker 镜像和容器的导入导出 1.1 镜像的导入导出 1.1.1 镜像的保存 通过镜像ID保存 方式一&#xff1a; docker save image_id > image-save.tar例如&#xff1a; rootUbuntu:/usr/local/docker/nginx# docker imagesREPOSITORY TAG IMAGE ID …

Java集合 List——针对实习面试

目录 Java集合 ListJava List的三种主要实现是什么&#xff1f;它们各自的特点是什么&#xff1f;Java List和Array&#xff08;数组&#xff09;的区别&#xff1f;Java List和Set有什么区别&#xff1f;ArrayList和Vector有什么区别&#xff1f;什么是LinkedList&#xff1f;…

超级干货O2OA数据中心-查询配置开发

O2OA提供的数据管理中心&#xff0c;可以让用户通过配置的形式完成对数据的汇总&#xff0c;统计和数据分组展现&#xff0c;查询和搜索数据形成列表数据展现。也支持用户配置独立的数据表来适应特殊的业务的数据存储需求。本文主要介绍如何在O2OA中开发和配置自定义数据查询语…

Unity中IK动画与布偶死亡动画切换的实现

在Unity游戏开发中&#xff0c;Inverse Kinematics&#xff08;IK&#xff09;是创建逼真角色动画的强大工具。同时&#xff0c;能够在适当的时候切换到布偶物理状态来实现死亡动画等效果&#xff0c;可以极大地增强游戏的视觉体验。本文将详细介绍如何在Unity中利用IK实现常规…

【ArcGISPro】单次将自己建立的工具箱添加至Arcpy中

新建工具箱 添加至Arcpy中 调用刚添加的工具箱

JVM的组成、字节码文件的组成

目录 java虚拟机的组成 字节码文件的组成 基础信息 常量池 字段 方法 属性 字节码相关的常用工具&#xff1a; 总结&#xff1a; 1、如何查看字节码文件&#xff1f; 2、字节码文件的核心组成有哪些&#xff1f; java虚拟机的组成 类加载器 ClassLoader运行时数据区…

新的服务器Centos7.6 安卓基础的环境配置(新服务器可直接粘贴使用配置)

常见的基础服务器配置之Centos命令 正常来说都是安装一个docker基本上很多问题都可以解决了&#xff0c;我基本上都是通过docker去管理一些容器如&#xff1a;mysql、redis、mongoDB等之类的镜像&#xff0c;还有一些中间件如kafka。下面就安装一个 docker 和 nginx 的相关配置…

Mysql COUNT() 函数详解

Mysql COUNT 函数详解 COUNT() 的几种用法COUNT(*)COUNT(1)COUNT(column)COUNT(*) 与 GROUP BYCOUNT(*) 与 GROUP BY 和 HAVING COUNT(expr) 的用法COUNT(DISTINCT expr)COUNT(expr) 带条件查询 写在最后 在使用Mysql的时候&#xff0c;作为开发者&#xff0c;聚合函数是肯定会…

yum下载时出现报错 Couldn‘t read a file:// file for file:///mnt/repodata/repomd.xml

得知说yum源指定的/mnt/没有镜像源 发现可能是镜像没有挂载成功 mount /dev/cdrom /mnt 清理一下缓存重新试一下 yum clean all yum install mod_ssl 解决

视觉SLAM数学基础

本文系统梳理从相机成像模型&#xff0c;通过不同图像帧之间的构造几何约束求解位姿变换&#xff0c;再根据位姿变换和匹配点还原三维坐标的过程&#xff0c;可以作为基于特征点法的视觉SLAM的数学基础。 1、相机成像模型 1.1、针孔相机模型 实际相机的成像方式通常很复杂&a…

书生大模型第四期闯关任务与笔记

书生大模型第四期闯关任务与笔记 入门岛第一关 Linux闯关任务&#xff1a;完成SSH连接与端口映射并运行hello_world.py笔记与过程SSH端口映射linux文件管理命令linux进程管理命令 第二关 Python闯关任务&#xff1a;Leetcode 383(笔记中提交代码与leetcode提交通过截图)闯关任务…

【React】深入理解 JSX语法

&#x1f308;个人主页: 鑫宝Code &#x1f525;热门专栏: 闲话杂谈&#xff5c; 炫酷HTML | JavaScript基础 ​&#x1f4ab;个人格言: "如无必要&#xff0c;勿增实体" 文章目录 深入理解 JSX语法1. JSX 简介2. JSX 的基本语法2.1 基本结构2.2 与普通 JavaScr…

MyBatis——增删查改(XML 方式)

1. 查询 1.1. 简单查询 使用注解的方式主要是完成一些简单的增删查改功能&#xff0c;如果要实现复杂的 SQL 功能&#xff0c;还是建议使用 XML 来配置映射语句&#xff0c;将 SQL 语句写在 XML 配置文件中 如果要操作数据库&#xff0c;需要做以下的配置&#xff0c;与注解…

YJN5216 手提式升降工作灯

YJN5216 手提式升降工作灯 产品简介&#xff1a; 适用于防汛应急抢修、铁路工务、电务、供电、运输等场所小范围检修、施工照明&#xff0c;也适用于电网、公消等行业小方位应急照明使用。 性能特点&#xff1a; 灯具体积小、重量轻,可以实现手提、背行两种携带方式。 灯具…

LeetCode题练习与总结:完美矩形--391

一、题目描述 给你一个数组 rectangles &#xff0c;其中 rectangles[i] [xi, yi, ai, bi] 表示一个坐标轴平行的矩形。这个矩形的左下顶点是 (xi, yi) &#xff0c;右上顶点是 (ai, bi) 。 如果所有矩形一起精确覆盖了某个矩形区域&#xff0c;则返回 true &#xff1b;否则…

Mac中安装OhMyZsh

Mac中安装OhMyZsh 文章目录 Mac中安装OhMyZsh一、Homebrew二、OhMyZsh1、Oh-My-Zsh配置1.1&#xff1a;主题配置1.2&#xff1a;插件配置&#xff08;语法高亮和自动提示&#xff09;1、zsh-autosuggestions&#xff08;需下载安装&#xff09;&#xff1a;高亮显示所有支持的命…

计算机毕业设计Python+图神经网络考研院校推荐系统 考研分数线预测 考研推荐系统 考研爬虫 考研大数据 Hadoop 大数据毕设 机器学习 深度学习

温馨提示&#xff1a;文末有 CSDN 平台官方提供的学长联系方式的名片&#xff01; 温馨提示&#xff1a;文末有 CSDN 平台官方提供的学长联系方式的名片&#xff01; 温馨提示&#xff1a;文末有 CSDN 平台官方提供的学长联系方式的名片&#xff01; 作者简介&#xff1a;Java领…

Llama旋转位置编码代码实现及详解

旋转位置编码RoPE 在旋转位置编码与Transformer和BERT之间的区别中介绍了旋转位置编码&#xff08;RoPE&#xff09;的特点和优势&#xff0c;这种输入长度动态可变的优势使得在Llama编码时&#xff0c;不需要掩码将多余的嵌入掩住。为了详细了解RoPE是如何实现的&#xff0c;…

如何保证Redis与MySQL双写一致性

什么是双写一致性问题&#xff1f; 双写一致性主要指在一个数据同时存在于缓存&#xff08;如Redis&#xff09;和持久化存储&#xff08;如MySQL&#xff09;的情况下&#xff0c;任何一方的数据更新都必须确保另一方数据的同步更新&#xff0c;以保持双方数据的一致状态。这一…