linked list(链表)142环形链表、206反转单链表

1. what is linked list

链表,线性表的一种

2. linked list structure

常见的链表结构有:

  • singly linked list 单链表
  • doubly linked list 双向链表
  • circularly linked 循环链表

3. 链表成环的相关问题

3.1通常判断链表成环的思路有:

①是利用追及问题的思想,由一快一慢的2个指针追及来判断是否成环。
②记录遍历过程中每一个节点,查看当前遍历到的是否之前已经访问过了。

3.2寻找cycle入口结点思路:

法①(比较好想,但是效率不太高)
使用哈希表来存储访问过的在遍历链表的时候看看是否有某个节点曾经访问过

法②(效率比较高,可以让时间复杂度保持在O(N),空间复杂度O(1))

假设环外长度设为 a,环的起点为x1,一快一慢两个指针相遇时的地点在x1前方距离为c的某个节点。
那么第一次相遇时slow指针走过的距离:a+c,fast指针走过的距离:a+c+未知距离(从x1开始、结束于环的起点,可能已经走了很多圈,也有可能一圈还没走完+c。
因为fast的速度是slow的两倍,所以fast走的距离是slow的两倍,所以 未知距离=a !!!
因此:
如果一个指针从链表的起点出发,另外一个从x1出发,且他们速度相同,他们一定会相遇在环的起点!!!

/*leetcode 142. Linked List Cycle II */

class Solution {
public:
    ListNode *detectCycle(ListNode *head) {
          if (head == NULL|| head->next ==NULL)
            return NULL;

        ListNode *slow= head;
        ListNode *fast= head;

        while (fast != NULL && fast->next != NULL)
        {   //fast 是 slow 速度的2倍
            slow =slow->next;
            fast =fast->next->next;
            
            //如果他们相遇了,证明环已经存在,现在进行第二步:在起点和相遇点放置速度相同的指针
            //他们一定会相遇在环的起点!
            if (slow == fast)
            {
                slow = head;
                while (slow != fast)
                {
                    slow = slow->next;
                    fast =fast->next;
                }
                return slow;
            }
        }
        return NULL;
    }
};

使用哈希表来实现如下(将节点的地址保存到哈希表中)

class Solution {
public:
    ListNode *detectCycle(ListNode *head) 
    {
        unordered_set<int>visited;
        if (head == NULL|| head->next ==NULL)
            return NULL;

        ListNode *pointer=head;
        while (pointer->next !=NULL)
        {
            if(visited.count(long(pointer)))
                return pointer;
            visited.insert(long(pointer));
            pointer=pointer->next;
        }
        return NULL;  
    }
};

3.3 反转链表

//遍历整个链表,用temp保存当前遍历的节点,每走一步将两个节点之间的指针反转
class Solution 
{
public:
    ListNode* reverseList(ListNode* head) 
    {
        ListNode*pt=head;
        ListNode*temp;
        if(pt==NULL) return head;
        while(pt->next!=NULL)
        {
            temp=pt->next;           //temp 在当前节点往前走一位
            pt->next=pt->next->next; //当前节点指向前面第二个人
            temp->next=head;         //前面第一个节点指向当前节点
            head=temp;               //head为当前节点前面前面一个节点
        }
        return head;

    }
};

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值