LeetCode学习笔记——链表(一)

个人博客:The Blog Of WaiterXiaoYY 欢迎来互相交流学习。

什么是链表

链表是数据结构的一种,它是一种线性数据结构,与数组相似,但与数组不同,在于它储存数据不一定需要一块完整连续的内存,它的每一个结点除了记录本身的数据之外,还记录着下一个结点的位置(指向下一个结点)。

在这里插入图片描述

单链表 [From:leetcode-cn.com]

链表有两种类型:单链表和双链表。

双链表与单链表的不同之处,在于双链表比单链表多了一个指向前一个结点的指针域。

在这里插入图片描述

双链表 [From:leetcode-cn.com]

- 链表结构表示
//单链表
struct Node{
	ElemType val;
	struct Node *next;
}ListNode;
//双链表
struct Node{
	ElemType val;
	struct Node *next;
	struct Node *pre;
}ListNode;

双指针技巧

顾名思义,双指针就是生成两个指针,利用两个指针对链表进行操作,经典问题是判断链表是否有环相交链表

- 题目:141.环形链表

给定一个链表,判断链表中是否有环。

为了表示给定链表中的环,我们使用整数 pos 来表示链表尾连接到链表中的位置(索引从 0 开始)。 如果 pos 是 -1,则在该链表中没有环。

示例1:

输入:head = [3,2,0,-4], pos = 1
输出:true
解释:链表中有一个环,其尾部连接到第二个节点。*

在这里插入图片描述

示例2:

输入:head = [1,2], pos = 0
输出:true
解释:链表中有一个环,其尾部连接到第一个节点。

在这里插入图片描述

解题思路

链表有环也就意味着如果一直遍历这个链表,那么是不会停止的,如果用两个指针,一个指针跑得快,一个跑的慢,快的那一个就可以追上前面那一个,当他们相等的时候,就说明该链表有环。

但要注意空链表和链表中只有一个结点的时候,如果只有一个结点,就不是环形链表,返回fasle。

代码
bool hasCycle(struct ListNode *head) {
	//空链表时则直接返回false
    if(!head)
        return false;
	//两个指针,且他们都指向链表的头指针
    struct ListNode* slow = head;
    struct ListNode* fast = head;
	//当快指针的下一个和下下个都不为空时,进入循环,这里就可以判断链表只有一个结点的情况
    while(fast->next && fast->next->next){
        fast = fast->next->next;     //快指针走两位
        if(fast == slow){
            return true;
        }
        else
            slow = slow->next;
    }
    return false;
}
- 题目:160.相交链表

编写一个程序,找到两个单链表相交的起始节点。

如下面的两个链表:

在这里插入图片描述

在节点 c1 开始相交。

示例1:

输入:intersectVal = 8, listA = [4,1,8,4,5], listB = [5,0,1,8,4,5], skipA = 2, skipB = 3
输出:Reference of the node with value = 8
输入解释:相交节点的值为 8 (注意,如果两个列表相交则不能为 0)。从各自的表头开始算起,链表 A 为 [4,1,8,4,5],链表 B 为 [5,0,1,8,4,5]。在 A 中,相交节点前有 2 个节点;在 B 中,相交节点前有 3 个节点。

在这里插入图片描述

示例2:

输入:intersectVal = 0, listA = [2,6,4], listB = [1,5], skipA = 3, skipB = 2
输出:null
输入解释:从各自的表头开始算起,链表 A 为 [2,6,4],链表 B 为 [1,5]。由于这两个链表不相交,所以 intersectVal 必须为 0,而 skipA 和 skipB 可以是任意值。
解释:这两个链表不相交,因此返回 null

在这里插入图片描述

解题思路

还是采用双指针的做法,但这次却不是快慢指针,而是两个指针同时进行,pA指向headA,pB指向headB,链表短的一方肯定先到达末尾,而到达末尾后,则改变指向长链表的头指针,继续遍历,当长的那方到达末尾后则指向短的一方头指针,如果相交,他们一定会在相交处相遇。

这里借用题解的一份图参考一下

在这里插入图片描述

其原理是一个数学差值问题,假设A链表有8个结点,B链表有6个结点,如果在A链表的第5个结点相交,也就是在B链表的第三个结点相交,在走到相交点处时,走的步数是一样的。

在这里插入图片描述

字丑请忽略

当相等的时候,返回即可。

代码
struct ListNode *getIntersectionNode(struct ListNode *headA, struct ListNode *headB) {
	//有一个为空链表都返回NULL
	if(!headA || !headB)
        return NULL;
    struct ListNode* pA = headA;
    struct ListNode* pB = headB;
    while(pA != pB){
        pA = pA == NULL?headB : pA->next;   //先判断pA是否到达了末尾,如果到了则pA=headB,否则pA指向下一个
        pB = pB == NULL?headA : pB->next;
    }
    return pA;
}

未整理完(2020.3.8)
个人博客:The Blog Of WaiterXiaoYY
欢迎来互相交流学习。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值