leetcode 链表的回文和相交

leetcode 链表的回文和相交

  • 1. 链表的回文结构
    • 1.1 题目描述
      • 1.1.1 接口函数
    • 1.2 大致框架
      • 1.2.1 思路分析
      • 1.2.2 具体步骤
    • 1.3 具体实现
  • 2. 相交链表
    • 2.1 题目描述
      • 2.1.1 接口函数
    • 2.2 大致框架
      • 2.2.1 思路分析
      • 2.2.2 具体步骤
    • 2.3 具体实现

1. 链表的回文结构

1.1 题目描述

牛客网把这道题标成了难题,然后leetcode标成了简单

题目链接

leetcode 链表的回文和相交_第1张图片

提示和进阶要求:

leetcode 链表的回文和相交_第2张图片

1.1.1 接口函数

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     struct ListNode *next;
 * };
 */


bool isPalindrome(struct ListNode* head){
     
}

1.2 大致框架

思路一:

强盗法:开一个足够大的数组,把链表的数据存到数组里面,通过数组将进行判断是否是回文的

但是空间复杂度是O(N),不符合要求

下面看一个可行的一般思路

1.2.1 思路分析

  1. 快慢指针找到中间节点先找到中间节点
    leetcode 链表的回文和相交_第3张图片
  2. 后半部分逆置
    leetcode 链表的回文和相交_第4张图片
  3. 再比较

这样的想法正好就是之前做过的两道题目的结合,一道是找中间节点,还有一个是反转链表

点链接可以传送,回顾之前的题目

leetcode 双指针方法解两道题

leetcode 206.反转链表

1.2.2 具体步骤

稍微结合一下两道题的方法就可以了

注意在开始之前要考虑极限情况 当只有一个节点和两个节点的时候正好是回文

if (head == NULL || head->next == NULL)
			return true;

判断是否回文部分

其实当我们输入的情况是偶数个时,第n/2-1个节点是指向中间节点的,而中间节点正好指向NULL,所以恰好不用对第n/2-1个节点指向空,依旧正常判断是否链表是否回文

while (head && prev)
		{
     
			if (head->val != prev->val)
				return false;
			head = head->next;
			prev = prev->next;
		}
		return true;

leetcode 链表的回文和相交_第5张图片

小结:

当然这道题在反转链表的时候可以选择头插法或者三指针逆置法或者递归法

1.3 具体实现

bool isPalindrome(struct ListNode* head) {
     
	if (head == NULL || head->next == NULL)
		return true;
	struct ListNode* slow, * fast, * prev, * cur, * next;
	slow = fast = head;

	//找到中间节点
	while (fast && fast->next)
	{
     
		slow = slow->next;
		fast = fast->next->next;
	}
	prev = NULL;
	cur = slow;
    next=cur->next;
	//后半部分逆置
	while (cur)
	{
     
		cur->next = prev;
		prev = cur;
		cur = next;
        if (next)
    	{
     
		    next = next->next;
	    }
	}
	//逐点比对
	while (head && prev)
	{
     
		if (head->val != prev->val)
			return false;
		head = head->next;
		prev = prev->next;
	}
	return true;
}

image-20211107225527898

2. 相交链表

2.1 题目描述

题目链接

leetcode 链表的回文和相交_第6张图片

给出示例:

leetcode 链表的回文和相交_第7张图片

提示与进阶

leetcode 链表的回文和相交_第8张图片

2.1.1 接口函数

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     struct ListNode *next;
 * };
 */
struct ListNode *getIntersectionNode(struct ListNode *headA, struct ListNode *headB) {
     
    
}

2.2 大致框架

2.2.1 思路分析

先要搞清楚本题的概念是:一个链表节点里面不可能有两个指针

leetcode 链表的回文和相交_第9张图片

找一个好方法判断相交

  • 只要判断链表的最后一个节的尾指针是否相同即可,当然也不能比较节点的值,一定要比较指针

所以我们要找到指针

  1. 计算出两个链表的节点数之差x
  2. 长链表指针先走x个
  3. 再同时往前走,第一个相同的节点就是两个链表的交点

2.2.2 具体步骤

先求AB链表的长度

    int lenA=0;
    int lenB=0;
    while(curA->next)//走到最后一个节点,不要走到空
    {
     
        curA=curA->next;
        lenA++;
    }
        while(curB->next)
    {
     
        curB=curB->next;
        lenB++;
    }

看到cur->next就得想到要在开头先判一下空

由一个为空肯定不相交,直接返回NULL

 //判空
    if(headA==NULL||headB==NULL)
    {
     
        return NULL;
    }

判断相等不相等,不相等必不相交

   if(curA!=curB)
    {
     
        return NULL;
    }

找出长的和差距数

    struct ListNode* longList=headA,*shortList=headB;
    if(lenB>lenA)
    {
     
        longList=headB;
        shortList=headA;
    }
    int gap=abs(lenB-lenA);

最后一起往前走,找到一样的点就返回任意一个即可

  while(gap--)
    {
     
        longList=longList->next;
    }
    while(longList!=shortList)
    {
     
            longList=longList->next;
            shortList=shortList->next;    
    }
    return longList;

2.3 具体实现

struct ListNode *getIntersectionNode(struct ListNode *headA, struct ListNode *headB) {
     
    //判空
    if(headA==NULL||headB==NULL)
    {
     
        return NULL;
    }
    struct ListNode*curA=headA, *curB=headB;
    int lenA=0;
    int lenB=0;
    while(curA->next)//走到最后一个节点,不要走到空
    {
     
        curA=curA->next;
        lenA++;
    }
        while(curB->next)
    {
     
        curB=curB->next;
        lenB++;
    }
    if(curA!=curB)
    {
     
        return NULL;
    }
    //长的先走差距数,再一起走
    struct ListNode* longList=headA,*shortList=headB;
    if(lenB>lenA)
    {
     
        longList=headB;
        shortList=headA;
    }
    int gap=abs(lenB-lenA);
    while(gap--)
    {
     
        longList=longList->next;
    }
    while(longList!=shortList)
    {
     
            longList=longList->next;
            shortList=shortList->next;    
    }
    return longList;
}

image-20211108110832880

小结:

这次的两道题目总的来说难度比上次高一点,像是综合一点的题型,主要好好思考好思路怎么实现,本质上来说代码难度并不是很高,还是需要多理解,多体会单链表

如果觉得有收获的话,希望大家一键三连

你可能感兴趣的:(leetcode,链表,leetcode,算法)