【力扣刷题】双指针在数组、链表中的妙用

在刷力扣的时候是按照代码随想录的顺序刷的,在刷前两章数组和链表时发现双指针法是一种经常用到,但是有时不知道该咋用的方法。文中有许多都是引用代码随想录的内容,仅做记录,并非完全原创,只是为了供自己也供大家整理并做个参考。

目录

1. 双指针从两边向中间移动

① 如力扣977题有序数组的平方(附上链接:代码随想录)

 ② 类似快速排序算法的双指针也可能解决某些数组或链表问题:

2. 双指针从头一起开始

如力扣206.反转链表(代码随想录)

 3. 快慢指针法

① 如27. 移除元素(代码随想录)

 ② 环形链表(代码随想录)

③ 滑动窗口:209.长度最小的子数组(代码随想录)


双指针法展现出效率的优势:通过两个指针在一个for循环下完成两个for循环的工作。

双指针法有以下几种常见类型:

1. 双指针从两边向中间移动

① 如力扣977题有序数组的平方(附上链接:代码随想录)

        比较两个指针指的数大小,选出大的存入另个数组

 ② 类似快速排序算法的双指针也可能解决某些数组或链表问题:

已知带头结点的双向循环链表头结点指针为list,除头结点外的每个链结点数据域值为一个整数。请写一算法,将链表中所有数据域值大于0的结点放在所有数据域值小于0的结点之前。若链表中除头结点外没有其他结点,算法返回0,否则,算法返回1。

/*设置两个指针变量p和q,初始时,p指向头结点右面那个结点,q指向头结点左面那个结点
(链表最右边那个结点)。然后,指针p从左向右扫描链表,查找数据域值小于0的结点,
而指针q从右向左扫描链表,查找数据域值大于0的结点。
若此时p指结点不是q指结点右面那个结点,交换两结点的数据域值,直到链表满足条件*/

int DMOVE(DLinkList list){
    DLinkList p = list-> rlink, q = link->llink;
    int temp;
    if(p == list)
        return 0;
    while(p != q){
        while(p->data > 0 && p != list)
            p = p->rlink;
        while(q->data < 0 && q != list)
            q = q->llink;
        if(q->rlink != p){
            temp = p->data;
            p->data = q->data;
            q->data = temp;
            p = p->rlink;
            q = q->llink;
            if(q->rlink == p || ( p == list && q == list))
                return 1;
        }
        else
            return 1;
    }
}

2. 双指针从头一起开始

这在单链表中很常见。设置一个cur,pre记录他的前一个结点,中间可能还需要temp来保存某中间结点。

如力扣206.反转链表(代码随想录)

 3. 快慢指针法

这是一种非常有技巧性的方法,也是比较难想到的高阶方法,非常巧妙。

① 如27. 移除元素(代码随想录)

  • 快指针:寻找新数组的元素 ,新数组就是不含有目标元素的数组
  • 慢指针:指向更新 新数组下标的位置

 ② 环形链表(代码随想录)

分别定义 fast 和 slow 指针,从头结点出发,fast指针每次移动两个节点,slow指针每次移动一个节点,如果 fast 和 slow指针在途中相遇 ,说明这个链表有环。

 从头结点出发一个指针,从相遇节点 也出发一个指针,这两个指针每次只走一个节点, 那么当这两个指针相遇的时候就是 环形入口的节点

【力扣刷题】双指针在数组、链表中的妙用_第1张图片

③ 滑动窗口:209.长度最小的子数组(代码随想录)

所谓滑动窗口,就是不断的调节子序列的起始位置和终止位置,从而得出我们要想的结果

你可能感兴趣的:(链表,leetcode,数据结构)