2021-1-19 删除结点 找第一个公共结点

题目1 删除链表中等于给定值 val 的所有节点。

x
示例:

输入: 1->2->6->3->4->5->6, val = 6
输出: 1->2->3->4->5

解1

常规方法,遍历链表,查看要删除的结点
注意!
遍历时,因为链表遍历指针无法返回,所以要以遍历结点的下一个值和删除值进行判断,便于删除

class Solution {
public:
    ListNode* removeElements(ListNode* head, int val) {
        //1. 定义一个标记结点,指向头,并将头节点也赋值给该节点
        ListNode* pTemp = new ListNode;
        pTemp->next = head;
        head = pTemp;//2. 遍历链表,遇到删除节点,则修改指针指向的内容
        while(pTemp->next)
        {
            if(pTemp->next->val == val)
                pTemp->next = pTemp->next->next;
            else
                pTemp = pTemp->next;
        }
        //3. 返回头节点
        return head->next;
    }
};

解2

递归算法,递归遍历每个几点,将递归返回值拼接到上一次递归的节点后面。

  1. 正常应该返回原结点即可;
  2. 若遇到删除节点,则将删除结点的下一个拼接到上一个结点
class Solution {
public:
    ListNode* removeElements(ListNode* head, int val) {
        if(head)
        {
        //如果未递归到头,继续深入
            head->next = removeElements(head->next,val);
        }
        //head的为NULL,开始返回
        //返回过程中,遇到删除结点
        if(head && val == head->val)
        	//该节点下一个返回个上一节点(即删除了该节点)
            return head->next;
        //正常返回本结点即可
        return head;
    }
};

题目2 输入两个链表,找出它们的第一个公共节点。

如下面的两个链表:
在这里插入图片描述

在节点 c1 开始相交。

解1 双指针法

假设:
链表1长度:l1+C;链表2长度:l2+C;
两个指针headA、headB分别遍历链表L1,L2
当headA走到NULL时,重新赋值L2头部,继续遍历;
当headB走到NULL时,重新赋值L1头部,继续遍历;

当两个链表走到第一个公共结点,都走l1+l2+C的长度,走的长度相同。

特殊情况

  1. 若有一个链表为NULL,则无交点
  2. 如下代码中,若两个链表无交点,会进入死循环。通过记录两个链表最后一个结点,判断是否相同,判断两链表有无交点
  3. 若两个链表长度相同且有公共节点,同时走到最后的NULL,虽然两指针相同,但是并非公共节点,需要继续遍历。
class Solution {
public:
    ListNode *getIntersectionNode(ListNode *headA, ListNode *headB) {
        //1. 如果有一个链表为NULL,则无交点
        if(headA == NULL || headB == NULL)
            return NULL;
        //标记两个链表头
        ListNode* pA = headA;
        ListNode* pB = headB;
        //标记两个链表尾
        ListNode* lA = NULL;
        ListNode* lB = NULL;
        //双指针循环遍历
        while((headA == NULL && headB == NULL) || headA != headB)
        {
            //遍历到尾结点
            if(headA && headA->next == NULL)
                lA = headA;
            if(headB && headB->next == NULL)
                lB = headB;
            //2. 如果两个链表尾都不同,则无交点
            if(lA && lB && lA!=lB)
                return NULL;
            //3. 循环遍历
            headA == NULL ? headA = pB : headA = headA->next;
            headB == NULL ? headB = pA : headB = headB->next;
        }
        return headA;
    }
};

解2

设置容器<ListNode*,int>,先遍历第一个链表,将每个结点对应值1;再遍历第二个链表,若遍历到的结点在容器中存在,返回该节点。

class Solution {
public:
    ListNode *getIntersectionNode(ListNode *headA, ListNode *headB) {
        //==================容器法=============================
        map<ListNode*,int> nodes;
        while(headA)
        {
            nodes[headA] = 1;
            headA = headA->next;
        }
        while(headB)
        {
            if(nodes[headB])
                return headB;
            headB = headB->next;
        }
        return NULL;
    }
};

解3 快慢指针

  1. 先求两个链表长度,假设相差k个元素。
  2. 再遍历链表,长链表指针先走k步,然后两个链表遍历指针一起移动,知道结点相同
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值