C算法-链表升级版

之前写过一篇简单的链表,现在更新些常用的手段。

  • 快慢指针

(一)快指针走两步,慢指针走一步
1、找中点,那么slow是间点

struct ListNode*fast, *slow;
fast = slow = head;
while(fast != NULL && fast->next != NULL) {
    slow= slow->next;
    fast = fast->next->next;
}

2、如果fast能跟slow相遇,那么可以用来判断是循环指针。

快慢指针的相遇,假设快的指针走了2X步,那么慢指针走了X步;由于两个指针相遇了,说明有环,假设1个环有C步,那么2X-X=kC;
在这里插入图片描述
所以慢指针走的步数X是一个环的整数倍;既然慢指针走了环的整数倍,所以慢指针当前所在的位置就是在一个奇怪的位置(假设第一段长度如图是A,那么相遇点就是还差A那么多走到环口的位置)

3、此刻,让快指针从头开始走,跟慢指针都一步一步走,快指针重新走了Y步,慢指针以及走了X+Y步,那么必然相遇于环入口

struct ListNode*fast, *slow;
bool hasCycle(struct ListNode *head) {
    fast = slow = head;
    while(fast != NULL && fast->next != NULL) {
        slow= slow->next;
        fast = fast->next->next;
        if(fast == slow) {
            return true;
        }
    }
    return false;
}
struct ListNode *detectCycle(struct ListNode *head) {
    if(hasCycle(head) == false) {
        return NULL;
    }
    fast = head;
    while(fast!=slow) {
        fast = fast->next;
        slow = slow->next;
    }
    return fast;
    
}

(二)快指针先走Z步,用来查找倒数第Z个元素
1、举例寻找倒数K个数

struct ListNode* getKthFromEnd(struct ListNode* head, int k){
    struct ListNode* fast, *slow;
    fast = slow = head;
    while(k) {
        fast = fast->next;
        k--;
    }
    while(fast!=NULL){
        fast = fast->next;
        slow = slow->next;
    }
    return slow;
}

2、申请节点指向head前,来处理head是单节点的问题

class Solution {
public:
    ListNode* removeNthFromEnd(ListNode* head, int n) {
        ListNode *tmp = new ListNode(0, head);
        ListNode *currNode = head;
        ListNode *preNode = tmp;

        for(int i = 0; i < n; i++) {
            currNode = currNode->next;
        }
        while (currNode != NULL) {
            currNode = currNode->next;
            preNode = preNode->next;
        }
        preNode->next = preNode->next->next;
        ListNode *ret = tmp->next;
        delete tmp;
        return ret;
    }
};
  • 链表翻转

需要一个指针NULL作为尾巴,每遍历一个节点,就把这个节点作为下一个的新尾巴;
在这里插入图片描述

    struct ListNode *slownext = NULL;
    struct ListNode *curr;
    while(slow != NULL) {
        curr = slow->next;
        slow->next = slownext;
        slownext = slow;
        slow = curr;
    }
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值