“双指针”法解决链表问题

    背景:单链表问题由于顺序遍历的特性,有时候执行一些操作的时候会出现问题看似需要多次遍历才能获取数据。使用双指针法能在一次遍历中获取更多的数据,也可以节约更多的额外控件。

    “双指针”就是用一个快指针一个慢指针同时进行单链表的顺序扫描。如此就可以使用快指针的时间差给慢指针提供更多的操作信息。下面是两个LeetCode下的习题。

(1)给定一个链表,删除链表的倒数第 个节点并返回头结点。

        例如,

给定一个链表: 1->2->3->4->5, 并且 n = 2.

当删除了倒数第二个节点后链表变成了 1->2->3->5.

思路:构建先导指针,快于后续指针n-1步,先导指针指向链表尾部时候,慢指针就指向倒数第n个节点

    ListNode* removeNthFromEnd(ListNode* head, int n) {
        ListNode* p = head;
        ListNode* pe = head;
        ListNode* pl = NULL;
        
        for (int i = 0; i < n - 1; ++i){
            pe = pe->next;
        }
        if (pe->next == NULL){
            return head->next;
        }
        pe = pe->next;
        p = p->next;
        pl = head;
    
        while(pe->next != NULL){
            pe = pe->next;
            p = p->next;
            pl = pl->next;
        }
        if (p->next){
            pl->next = p->next;
        }
        else{
            pl->next = NULL;
        }
        return head;
    }

这个答案可以用“dummy node”来优化:增加n-1个先导节点进行优化,这样就不用进行比较繁杂的判空操作,直接告诉向下遍历即可。

(2)给定一个链表,判断链表中否有环。

传统思路:找个容器把出现的点存起来,出现重复点就判断成环(缺点很明显:额外内存占用)

bool hasCycle(ListNode *head) {
    std::set<ListNode*> sl;
    if (!head){
        return false;
    }
    while(head->next){
        if (sl.find(head) != sl.end()){
            return true;
        }
        else{
           sl.insert(head);
           head = head->next;
        }
     }
     return false;
}

双指针思路:快指针比慢指针先走,如果快指针被慢指针追上,说明进入闭环

ListNode* fastNode = head;
ListNode* slowNode = head;
        
if (head == nullptr)
{
     return false;
}
        
while (fastNode && fastNode->next)
{
      slowNode = slowNode->next;
      fastNode = fastNode->next->next;
            
      if (slowNode == fastNode)
      {
           return true;
      }
}
总结:用双指针能够靠速度差或者位置差更加方便的处理定位和列表结构的信息,从而构造出更低复杂度的算法。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值