【算法练习】双指针

这篇具有很好参考价值的文章主要介绍了【算法练习】双指针。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

移动零

【算法练习】双指针,小嘟陪你刷题系列,算法,数据结构

算法原理:
数组划分(数组分块)

【算法练习】双指针,小嘟陪你刷题系列,算法,数据结构
两个指针作用:
cur:从左到右扫描数组,遍历数组
dest:已处理的区间内,非零元素的最后一个位置

三个区间:
[0.dest]:已经处理过的非零元素
[dest+1, cur-1]:处理过的零元素
[cur,n-1] :待处理元素

情况1:当cur遇到0元素的时候,直接让cur向后移动一位
【算法练习】双指针,小嘟陪你刷题系列,算法,数据结构
【算法练习】双指针,小嘟陪你刷题系列,算法,数据结构

情况2:当cur遇到非零元素的时候,dest往后一位。然后交换这两个位置的元素,然后cur+1
【算法练习】双指针,小嘟陪你刷题系列,算法,数据结构
【算法练习】双指针,小嘟陪你刷题系列,算法,数据结构
【算法练习】双指针,小嘟陪你刷题系列,算法,数据结构

情况3:当cur遍历到n时,就完成了区间的划分
【算法练习】双指针,小嘟陪你刷题系列,算法,数据结构

总结:
cur从前往后遍历的过程中:
1.遇到0元素:cur元素++
2.遇到非零元素:
swap(dest+1,cur);
dest++,cur++;

代码文章来源地址https://www.toymoban.com/news/detail-563905.html

class Solution {
    public void moveZeroes(int[] nums) {
        for(int cur = 0, dest = -1; cur < nums.length; cur++) {
            if(nums[cur] != 0) {
                dest++; 
                int tmp = nums[cur];
                nums[cur] = nums[dest];
                nums[dest] = tmp;
            }
        }
    }
}

复写零

【算法练习】双指针,小嘟陪你刷题系列,算法,数据结构

算法原理:
解法:双指针算法
先根据“异地”操作,然后优化成双指针下的“就地”操作
异地操作就是说开辟一个新的数组,定义一个指针指向原始数组,定义一个新指针指向新数组,然后进行操作。
就地操作,就是把两个指针定义在同一个数组上。

1.先找到最后一个“复写”的数;
双指针算法:
1)先判断cur位置的值
2)决定dest向后移动一步或者两步
3.)判断一下dest是否已经到结束为止
4)cur++
1.5. 处理一下边界情况
n-1 -> 0
cur–
dest -=2
2.“从后向前”完成复写操作;

代码

public static void duplicateZeros(int[] arr) {
        int cur = 0, dest = -1, n = arr.length;
        // 1. 先找到最后一个需要复写的数
        while (cur < n) {
            if (arr[cur] == 0) dest += 2;
            else dest += 1;
            if (dest >= n - 1) break;
            cur++;
        }
        // 1.5 处理一下边界情况
        if (dest == n) {
            arr[n - 1] = 0;
            cur--;
            dest -= 2;
        }
        // 2. 从后向前完成复写操作
        while (cur >= 0) {
            if (arr[cur] != 0) arr[dest--] = arr[cur--];
            else {
                arr[dest--] = 0;
                arr[dest--] = 0;
                cur--;
            }
        }
    }

快乐数

【算法练习】双指针,小嘟陪你刷题系列,算法,数据结构

算法原理:
判断链表是否有环
【算法练习】双指针,小嘟陪你刷题系列,算法,数据结构

解法:快慢双指针
1.定义快慢指针
2.慢指针每次向后移动一步,快指针每次向后移动两步
3.判断相遇时候的值即可

代码

class Solution {
    public int bitSum(int n) { // 返回n这个数每一位上的平方和
        int sum = 0;
        while (n != 0) {
            int t = n % 10;
            sum += t * t;
            n /= 10;
        }
        return sum;
    }

    public boolean isHappy(int n) {
        int slow = n;
        int fast = bitSum(n);
        while (slow != fast) {
            slow = bitSum(slow);
            fast = bitSum(bitSum(fast));
        }
        return slow == 1;
    }
}

盛最多水的容器

【算法练习】双指针,小嘟陪你刷题系列,算法,数据结构

解法思路:
解法一:暴力枚举O(N^2)
解法二:利用单调性,使用双指针解决问题O(N)

代码

public int maxArea(int[] height) {
        int left = 0;
        int right = height.length - 1;
        int ret = 0;
        while (left < right) {
            int v = Math.min(height[left], height[right]) * (right - left);
            ret = Math.max(ret, v);
            if (height[left] < height[right]) left++;
            else right--;
        }
        return ret;
    }

有效三角形的个数

【算法练习】双指针,小嘟陪你刷题系列,算法,数据结构

算法原理:
利用单调性,使用双指针算法来解决问题
先对整个数组排序。
先固定最大的数
在最大的数的左区间内,使用双指针算法,快速统计出符合要求的三元组的个数

代码

import java.util.Arrays;

public class Solution {
    public int triangleNumber(int[] nums) {
        // 1. 优化:排序
        Arrays.sort(nums);

        // 2. 利用双指针解决问题
        int ret = 0, n = nums.length;
        for (int i = n - 1; i > 0; i--) {// 先固定最大的数
            // 利用双指针快速统计出符合三元组的个数
            int left = 0, right = i - 1;
            while (left < right) {
                if (nums[left] + nums[right] > nums[i]) {
                    ret += right - left;
                    right--;
                } else {
                    left++;
                }
            }
        }
        return ret;
    }
}

和为s的两个数

【算法练习】双指针,小嘟陪你刷题系列,算法,数据结构

算法原理:
利用单调性,使用双指针算法解决问题

代码

public int[] twoSum(int[] nums, int target) {
        int left = 0, right = nums.length - 1;
        while (left < right) {
            int sum = nums[left] + nums[right];
            if (sum > target) right--;
            else if (sum < target) left++;
            else return new int[]{nums[left], nums[right]};
        }
        // 照顾编译器
        return new int[]{0};
}

三数之和

【算法练习】双指针,小嘟陪你刷题系列,算法,数据结构

算法原理:
排序+双指针
1.排序;
2.固定一个数i
3.在该数后面的区间内,利用“双指针算法”,快速找到两个的和等于-i即可
处理细节:
1.去重 :找到一种结果之后,left和right指针要跳过重复元素;当使用完一次双指针算法之后,i也需要跳过重复元素
2.不漏 : 找到一种结果之后,不要”停“,缩小区间,继续寻找

代码

class Solution {
    public List<List<Integer>> threeSum(int[] nums) {

        List<List<Integer>> ret = new ArrayList<>();
        // 1. 排序
        Arrays.sort(nums);

        // 2. 利于双指针解决问题
        int n = nums.length;
        for (int i = 0; i < n;) {//固定数 a
            if (nums[i] > 0) break;// 小优化
            int left = i + 1;
            int right = n - 1, target = -nums[i];
            while (left < right) {
                int sum = nums[left] + nums[right];
                if (sum > target) right--;
                else if (sum < target) left++;
                else {
                    // nums[i] nums[left] nums[right]
                    ret.add(new ArrayList<Integer>(Arrays.asList(nums[i], nums[left], nums[right])));
                    // 缩小区间,继续寻找
                    left++;
                    right--;
                    // 去重
                    while (left < right && nums[left] == nums[left - 1]) {
                        left++;
                    }
                    while (left < right && nums[right] == nums[right + 1]) {
                        right--;
                    }
                }
            }
            // 去重: i
            i++;
            while (i < n && nums[i] == nums[i - 1]) i++;
        }
        return ret;
    }
}

四数之和

【算法练习】双指针,小嘟陪你刷题系列,算法,数据结构

算法原理:
排序+双指针
1.依次固定一个数a;
2.在a后面的区间内,利用“三数之和“找到三个数,使这三个数的和等于 target-a即可

代码

public List<List<Integer>> fourSum(int[] nums, int target) {

        List<List<Integer>> ret = new ArrayList<>();

        // 1. 排序
        Arrays.sort(nums);

        // 2. 利用双指针解决问题
        int n = nums.length;
        for (int i = 0; i < n; ) {// 固定数a
            // 三数之和
            for (int j = i + 1; j < n; ) {// 固定数 b
                // 双指针
                int left = j + 1, right = n - 1;
                long aim = (long)target - nums[i] - nums[j];
                while (left < right) {
                    int sum = nums[left] + nums[right];
                    if (sum > aim) right--;
                    else if (sum < aim) left++;
                    else {
                        ret.add(Arrays.asList(nums[i], nums[j], nums[left++], nums[right--]));
                        // 去重一
                        while (left < right && nums[left] == nums[left - 1]) left++;
                        while (left < right && nums[right] == nums[right + 1]) right--;
                    }
                }
                // 去重二
                j++;
                while (j < n && nums[j] == nums[j - 1]) j++;
            }
            // 去重三
            i++;
            while (i < n && nums[i] == nums[i - 1]) i++;
        }
        return ret;
    }

到了这里,关于【算法练习】双指针的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 【算法练习】双指针

    算法原理: 数组划分(数组分块) 两个指针作用: cur:从左到右扫描数组,遍历数组 dest:已处理的区间内,非零元素的最后一个位置 三个区间: [0.dest]:已经处理过的非零元素 [dest+1, cur-1]:处理过的零元素 [cur,n-1] :待处理元素 情况1:当cur遇到0元素的时候,直接让cur向后移

    2024年02月16日
    浏览(36)
  • 算法刷题记录-双指针/滑动窗口(LeetCode)

    思路 根据题目描述,我们可以知道,如果要将某个单词定义为可扩张(stretchy),需要满足如下两个条件: 所以,我们在实现的时候,可以通过两个指针p1和p2,分别指向s和word,分别统计连续的相同字符数量c1和c2,然后再通过上述的两个条件进行判断,即:如果 则表示该单

    2024年02月09日
    浏览(43)
  • 数据结构算法leetcode刷题练习(1)

    给定一个三角形 triangle ,找出自顶向下的最小路径和。 每一步只能移动到下一行中相邻的结点上。相邻的结点 在这里指的是 下标 与 上一层结点下标 相同或者等于 上一层结点下标 + 1 的两个结点。也就是说,如果正位于当前行的下标 i ,那么下一步可以移动到下一行的下标

    2023年04月24日
    浏览(54)
  • PTA-SQL刷题系列之基础篇——查询补充练习(一)

    目录 10-1 查询图 10--2 查询2018年以后出版的图书的全部信息 10-3 查询图书表中售价介于50元到70元之间的图书的全部信息 10-4 查询图书表中条形码左边开始三个字符是“TP3”的图书的全部信息 10-5 查询图书表中书名为“C语言程序设计”和“VB程序设计”的两本书的全部信息 之一

    2023年04月22日
    浏览(37)
  • 算法刷题营【Day2】:: 双指针算法应用:滑动窗口 :209. 长度最小的子数组

    本内容是笔者结合《代码随想录》总结所得,记录学习过程,分享知识! 目录: 1. 开篇例题:209. 长度最小的子数组 2. 题解参考 - - 2.1 方法一:暴力法 - - 2.2 方法二:滑动窗口 3. 方法思路点拨:滑动窗口 - - 3.1 直白解释 - - 3.2 本题思路点拨 4. 相关题集 1. 开篇例题:209. 长度

    2024年02月04日
    浏览(47)
  • 算法刷题营【Day1】:: 27. 移除元素:快慢指针在顺序表中的应用与相关刷题

    本内容是笔者结合《代码随想录》总结所得,记录学习过程,分享知识! 目录: 1. 开篇例题:27. 移除元素 2. 题解参考 3. 题解思路 4. 相关题 [ - - 4.1 26. 删除有序数组中的重复项 ] [ - - 4.1 283. 移动零 ] 5. 相关题题解及简要思路 - - 5.1 26. 删除有序数组中的重复项 - - 5.1 283. 移动

    2024年02月06日
    浏览(95)
  • 【算法系列篇】双指针

    朋友们,大家好啊,从今天开始我将陆续为大家更新关于算法方面的文章,如果大家对于算法感兴趣的话,欢迎大家订阅我的算法专栏。 双指针算法(Two Pointers Algorithm)是一种常用的算法技巧,通常用于数组、链表或其他线性数据结构中的问题。该算法使用两个指针在数据

    2024年02月12日
    浏览(33)
  • 数据结构与算法系列之习题练习

    💗 💗 博客:小怡同学 💗 💗 个人简介:编程小萌新 💗 💗 如果博客对大家有用的话,请点赞关注再收藏 🌞 括号匹配问题。 用队列实现栈。 用栈实现队列。 设计循环队列。 有效的括号 //用栈来实现 //左括号进栈 右括号出栈并销毁如果不匹配则return //设置两个队列,入栈

    2024年02月11日
    浏览(47)
  • 【算法|双指针系列No.2】leetcode1089. 复写零

    个人主页:平行线也会相交 欢迎 点赞👍 收藏✨ 留言✉ 加关注💓本文由 平行线也会相交 原创 收录于专栏【手撕算法系列专栏】【LeetCode】 🍔本专栏旨在提高自己算法能力的同时,记录一下自己的学习过程,希望对大家有所帮助 🍓希望我们一起努力、成长,共同进步。

    2024年02月13日
    浏览(40)
  • 【算法|双指针系列No.4】leetcode11. 盛最多水的容器

    个人主页:兜里有颗棉花糖 欢迎 点赞👍 收藏✨ 留言✉ 加关注💓本文由 兜里有颗棉花糖 原创 收录于专栏【手撕算法系列专栏】【LeetCode】 🍔本专栏旨在提高自己算法能力的同时,记录一下自己的学习过程,希望对大家有所帮助 🍓希望我们一起努力、成长,共同进步。

    2024年02月06日
    浏览(49)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包