【数据结构与算法】之多指针算法经典问题

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

前言

【数据结构与算法】之多指针算法经典问题

本文为 【数据结构与算法】多指针算法经典问题 相关介绍,下边将对链表反转(包含迭代反转链表递归反转头插法反转),双指针-快慢指针(包含寻找单向无环链表的中点判断单向链表是否有环及找环入口),双指针-左右指针(包含两数之和二分查找)等相关多指针算法进行详尽介绍~

📌博主主页:小新要变强 的主页
👉Java全栈学习路线可参考:【Java全栈学习路线】最全的Java学习路线及知识清单,Java自学方向指引,内含最全Java全栈学习技术清单~
👉算法刷题路线可参考:算法刷题路线总结与相关资料分享,内含最详尽的算法刷题路线指南及相关资料分享~
👉Java微服务开源项目可参考:企业级Java微服务开源项目(开源框架,用于学习、毕设、公司项目、私活等,减少开发工作,让您只关注业务!)


目录

【数据结构与算法】之多指针算法经典问题

一、链表反转

链表反转公用代码:

public class ReverseLink {
    public static void main(String[] args) {
     
    }

    // 遍历的方法
    public static void print(Node<Integer> head) {
        Node<Integer> current = head;
        while (current != null) {
            System.out.println(current.t);
            current = current.next;
        }
    }

    private static class Node<T> {
        private T t;
        private Node<T> next = null;

        public Node(T t) {
            this.t = t;
        }
    }


    private static Node<Integer> buildLink() {
        Node<Integer> head = new Node<>(1);
        Node<Integer> node2 = new Node<>(2);
        Node<Integer> node3 = new Node<>(3);
        Node<Integer> node4 = new Node<>(4);
        Node<Integer> node5 = new Node<>(5);

        head.next = node2;
        node2.next = node3;
        node3.next = node4;
        node4.next = node5;
        return head;
    }

}

1️⃣迭代反转链表

链表翻转最大的问题就是,对于单链表而言,引用一旦指向新的节点,就会于之前关联的节点失去联系,所以我们可以使用三个引用临时保存需要操作的节点:
【数据结构与算法】之多指针算法经典问题

  • 第一个和第二个引用用来进行反转操作
  • 第三个引用用来保存后边的节点,防止关联失效

【数据结构与算法】之多指针算法经典问题

  • 以后每一步操作,只需要将三个临时节点统一向后移动即可,这就是一个遍历的过程

【数据结构与算法】之多指针算法经典问题

代码如下:

// 采用单个指针的方式,迭代进行逆转
public static Node<Integer> reverseLink(Node<Integer> head) {

    if (head == null || head.next == null) {
        return head;
    }

    // 定义三个引用,分别代表当前节点,以及他的前后节点
    Node<Integer> prevNode = null;
    Node<Integer> current = head;
    Node<Integer> nextNode = head.next;

    // 先进行一个翻转翻转
    current.next = prevNode;

    while (nextNode != null) {

        // 三个指针,统一移动
        prevNode = current;
        current = nextNode;
        nextNode = current.next;

        // 翻转
        current.next = prevNode;

        // 确定到达尾部,定义新的头结点
        if (nextNode == null) {
            head = current;
        }
    }
    return head;
}

2️⃣递归反转

  • 递归翻转的思路和之前的思路恰好相反,递归往往都是这个样子:

【数据结构与算法】之多指针算法经典问题

  • 我们使用递归将后续的节点成功反转:

【数据结构与算法】之多指针算法经典问题

  • 接下来只需要将A和B反转即可。

代码如下:

// 递归遍历链表
public static Node<Integer> recursiveReverseLink(Node<Integer> head) {

    if (head == null || head.next == null) {
        return head;
    }

    // 上边的A和B的反转,node是反转后的头节点
    Node<Integer> node = recursiveReverseLink(head.next);
    head.next.next = head;
    head.next = null;

    return node;

}

3️⃣头插法反转

头插法的思路比较简单,就是从头开始遍历,每次摘下一个节点,然后使用头插法,拼接成一个新的链表:

【数据结构与算法】之多指针算法经典问题

代码如下:

// 使用头插法
public static Node<Integer> headInsertReverseLink(Node<Integer> head) {

    if (head == null || head.next == null) {
        return head;
    }

    // newHead表示的是新建的链表的头结点
    Node<Integer> newHead = null, temp;

    while (head != null) {
        // 临时节点指向head
        temp = head;
        // head后移,相当于将头结点摘除了
        head = head.next;
        temp.next = newHead;
        newHead = temp;
    }

    return newHead;
}

二、双指针-快慢指针

1️⃣寻找单向无环链表的中点

【数据结构与算法】之多指针算法经典问题

代码如下:

public static Node findMiddle(Node head){
    Node fast = head,slow = head;
    while (fast != null && fast.next != null){
        fast = fast.next.next;
        slow = slow.next;
    }
    return slow;
}

2️⃣判断单向链表是否有环及找环入口

题目: 给定一个单向的链表,判断该链表是否有换,如果不存在换返回null,如果存在,则返回链表开始入环的第一个节点。

说明: 不允许修改给定的链表。如下图:应该返回C这个节点。

【数据结构与算法】之多指针算法经典问题
判断有没有环思路: 我们同样使用快慢指针,fast 与slow,一旦fast追上slow就说明存在环。

寻找换的入口,是一个比较麻烦的事情,我们有基本的数学推导如下,这里有个一直条件,fast一旦追上slow说明fast比slow正好快了一圈。

如下图所示,设链表中环外部分的长度为 a。slow 指针进入环后,又走了 b 的距离与 fast 相遇。此时,fast 指针已经走完了环的 n 圈,因此它走过的总距离为 :
a + ( b + c ) + b = a + 2 b + c a+(b+c)+b=a+2b+c a+(b+c)+b=a+2b+c
【数据结构与算法】之多指针算法经典问题
根据题意,任意时刻,fast 指针走过的距离都为 slow 指针的 2 倍。因此,我们有:
a + 2 b + c = 2 ( a + b ) ⟹ a = c a+2b+c=2(a+b)⟹a=c a+2b+c=2(a+b)a=c 有了这个等量关系,我们会发现:在我们的题目中,从相遇点到入环点的距离,恰好等于从链表头部到入环点的距离。

因此,当发现 slow 与 fast 相遇时,我们再额外使用一个指针 ptr。起始,它指向链表头部;随后,它和slow 每次向后移动一个位置。最终,它们会在入环点相遇。

代码如下:

public class Solution {
    public ListNode detectCycle(ListNode head) {
        if (head == null) {
            return null;
        }
        ListNode slow = head, fast = head;
        while (fast != null) {
            slow = slow.next;
            if (fast.next != null) {
                fast = fast.next.next;
            } else {
                return null;
            }
            if (fast == slow) {
                ListNode ptr = head;
                while (ptr != slow) {
                    ptr = ptr.next;
                    slow = slow.next;
                }
                return ptr;
            }
        }
        return null;
    }
}

三、双指针-左右指针

1️⃣两数之和

输入一个【有序数组】和一个目标值,找到数组中的两个数相加等于目标值,输出两个数字的下标:

【数据结构与算法】之多指针算法经典问题

代码如下:

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){
            return new int[]{left+1,right+1};
        } else if(sum < target){
            left++;
        } else if (sum > target){
            right--;
        }
    }
    return new int[]{-1,-1};
}

2️⃣二分查找

给定一个有序数组,和一个目标值,找出目标值出现的位置,返回下标,找不到则返回-1:
【数据结构与算法】之多指针算法经典问题

代码如下:

public static int binarySearch(int[] nums,int target){
    int left = 0,right = nums.length -1;
    while (left <= right){
        int middle = (left + right)/2;
        if(nums[middle] == target){
            return middle;
        } else if(nums[middle] < target){
            left = middle+1;
        } else if (nums[middle] > target){
            right = middle -1;
        }
    }
    return -1;
}

后记

【数据结构与算法】之多指针算法经典问题

👉Java全栈学习路线可参考:【Java全栈学习路线】最全的Java学习路线及知识清单,Java自学方向指引,内含最全Java全栈学习技术清单~
👉算法刷题路线可参考:算法刷题路线总结与相关资料分享,内含最详尽的算法刷题路线指南及相关资料分享~文章来源地址https://www.toymoban.com/news/detail-434976.html

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

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

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

相关文章

  • 【数据结构与算法】十大经典排序算法-插入排序

    【数据结构与算法】十大经典排序算法-插入排序

    🌟 个人博客: www.hellocode.top 🏰 Java知识导航: Java-Navigate 🔥 CSDN: HelloCode. 🌞 知乎 :HelloCode 🌴 掘金 :HelloCode ⚡如有问题,欢迎指正,一起学习~~ 插入排序(Insertion Sort)是一种简单直观的排序算法,其基本思想是将一个记录插入到已排好序的有序序列中,直到所有记录

    2024年02月13日
    浏览(13)
  • 200个经典面试题(算法思想+数据结构)_1

    1. 爬楼梯 70. Climbing Stairs (Easy) 题目描述:有 N 阶楼梯,每次可以上一阶或者两阶,求有多少种上楼梯的方法。 定义一个数组 dp 存储上楼梯的方法数(为了方便讨论,数组下标从 1 开始),dp[i] 表示走到第 i 个楼梯的方法数目。 第 i 个楼梯可以从第 i-1 和 i-2 个楼梯再走一步

    2024年02月13日
    浏览(8)
  • 【数据结构与算法】:10道链表经典OJ

    【数据结构与算法】:10道链表经典OJ

    思路1:遍历原链表,将 val 所在的节点释放掉。(太麻烦) 思路2:创建新链表,再遍历原链表,找到不为 val 的节点尾插到新链表。 思路1代码实现如下: 注意: 1.当链表为空时,直接返回NULL即可。 2.当尾插上最后一个有效节点时,此时它的 next 可能还与最后一个节点相链接,

    2024年04月14日
    浏览(8)
  • 【Elacticsearch】 原理/数据结构/面试经典问题整理

    【Elacticsearch】 原理/数据结构/面试经典问题整理

    对Elacticsearch 原理/数据结构/面试经典问题整理的文章; 映射 | Elasticsearch: 权威指南 | Elastic 目录 Elacticsearch介绍 原理 建立索引原理 查询索引原理 更新索引原理 删除索引原理 分片副本机制,集群发现选举机制 ,负载机制,容错机制,扩容机制 数据类型 数据结构 先介绍倒排

    2024年02月10日
    浏览(9)
  • 【数据结构】单链表经典算法题的巧妙解题思路

    【数据结构】单链表经典算法题的巧妙解题思路

    目录 题目 1.移除链表元素 2.反转链表 3.链表的中间节点 4.合并两个有序链表 5.环形链表的约瑟夫问题 解析 题目1:创建新链表 题目2:巧用三个指针 题目3:快慢指针 题目4:哨兵位节点 题目5:环形链表   介绍完了单链表,我们这次来说几个经典的题目,本篇的题目衔接下一

    2024年04月28日
    浏览(30)
  • 头歌数据结构实训参考---十大经典排序算法

    可通过 目录 快速查阅对应排序算法

    2024年02月04日
    浏览(14)
  • 数据结构与算法----复习Part 8 (链表双指针)

    本系列是算法通关手册LeeCode的学习笔记 算法通关手册(LeetCode) | 算法通关手册(LeetCode) (itcharge.cn) 本系列为自用笔记,如有版权问题,请私聊我删除。 目录 一,双指针简介(Two Pointers) 二,起点不一致的快慢指针 三,步长不一致的快慢指针 判断链表中是否含有环: 四

    2024年02月19日
    浏览(39)
  • 【数据结构与算法】三个经典案例带你了解动态规划

    【数据结构与算法】三个经典案例带你了解动态规划

    从表中我们可以看到,最大的公共子串长度为2,一共有两个长度为2的公共子串,分别是第一个字符串的第2个字符到第3个字符和第一个字符串的第3个字符到第4个字符,即 ba 和 ac 根据上面的方法,我们来用代码封装一下求取最大公共子串的函数 function publicStr(s1, s2) { // 创建

    2024年04月09日
    浏览(9)
  • 手撕数据结构与算法——树(三指针描述一棵树)

    手撕数据结构与算法——树(三指针描述一棵树)

    📖作者介绍:22级树莓人(计算机专业),热爱编程<目前在c++阶段, 因为最近参加新星计划算法赛道(白佬),所以加快了脚步,果然急迫感会增加动力 ——目标Windows,MySQL,Qt,数据结构与算法,Linux,多线程,会持续分享学习成果和小项目的 📖作者主页:king南星 📖

    2024年01月17日
    浏览(52)
  • 算法竞赛备赛之经典数据结构训练提升,暑期集训营培训

    算法竞赛备赛之经典数据结构训练提升,暑期集训营培训

    我们将结构体和指针结合来实现链表 我们算法主要是用数组来模拟链表,这样效率会高一些。 数组模拟单链表 邻接表:存储图和树 实现一个单链表,链表初始为空,支持三种操作: 向链表头插入一个数 删除第k个插入的数后面的数 在第k个前面插入一个数 数组模拟双链表的

    2024年02月16日
    浏览(6)

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

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

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

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

二维码1

领取红包

二维码2

领红包