玩转双指针

一、算法简介

双指针主要用于遍历数组,两个指针指向不同的元素,从而协同完成任务。也可以延伸到多
个数组的多个指针。

若两个指针指向同一数组,遍历方向相同且不会相交,则也称为滑动窗口(两个指针包围的
区域即为当前的窗口),经常用于区间搜索

若两个指针指向同一数组,但是遍历方向相反,则可以用来进行搜索,待搜索的数组往往是
排好序的。

二、指针小知识

对于C++ 语言,指针还可以玩出很多新的花样。一些常见的关于指针的操作如下

(1)指针与常量

简而言之,就是const修饰谁,谁就是常量,这里把“*”(星号),理解为独立的字符——指针,就比较好理解了

i. const int * p2, 为常量指针(先读const——常量,再读*——指针),即指向一个常量(const int)的指针。

ii. int * const p3,为指针常量(先读*——指针,再const——常量),指针本身是常量,指向的地址不可以变化,但是指向的地址所对应的内容(值)可以变化。

 

 

(2)指针函数与函数指针

#include <iostream>

// addition是指针函数,一个返回类型是指针的函数
int* addition(int a, int b) {
int* sum = new int(a + b);  // 注意,在函数内new出来的,出函数是不会自动销毁的,一定要在某处通过delete手动销毁。
return sum;
}

int subtraction(int a, int b) {
return a - b;
}

int operation(int x, int y, int (*func)(int, int)) {
return (*func)(x,y);
}

// minus是函数指针,指向函数的指针
int (*minus)(int, int) = subtraction;


int main()
{
    int* m = addition(1, 2);  // 1 + 2 = 3
    int n = operation(3, *m, minus);  // 3 -3 = 0
    std::cout << *m << std::endl;
    std::cout << n << std::endl;
    return 0;
}

 输出结果为:

 

三、例题

167. 两数之和 II - 输入有序数组

因为数组已经排好序,我们可以采用方向相反的双指针来寻找这两个数字,一个初始指向最
小的元素,即数组最左边,向右遍历;一个初始指向最大的元素,即数组最右边,向左遍历。

Leetcode 88. 合并两个有序数组

 

Leetcode 142. 环形链表 II

对于链表找环路的问题,有一个通用的解法——快慢指针(Floyd 判圈法,其有数学证明)。

给定两个指针,分别命名为slow 和fast,起始位置在链表的开头。(步骤1) 每次fast 前进两步,slow 前进一步。
如果fast可以走到尽头,那么说明没有环路;如果fast 可以无限走下去,那么说明一定有环路,且一定存
在一个时刻slow 和fast 相遇。(步骤2)当slow 和fast 第一次相遇时,我们将fast 重新移动到链表开头,并
让slow 和fast 每次都前进一步。(步骤3)当slow 和fast 第二次相遇时,相遇的节点即为环路的开始点。

 

该算法可以:

  • 判断链表是否有环
  • 计算环的长度
  • 寻找环的起点
/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode(int x) : val(x), next(NULL) {}
 * };
 */
class Solution {
public:
    ListNode *detectCycle(ListNode *head) {
        ListNode *fast = head, *slow = head;
        // 步骤1
        do  
        {
            if (!fast || !fast->next) return nullptr;
            fast = fast->next->next;
            slow = slow->next;
        } while (fast != slow);
        // 步骤2
        fast = head;
        while (fast != slow)
        {
            fast = fast->next;
            slow = slow->next;
        }
        // 步骤3
        return fast;
    }
};

  

 

 
posted @ 2022-12-04 11:54  blogzzt  阅读(29)  评论(0编辑  收藏  举报