题目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
递归算法,递归遍历每个几点,将递归返回值拼接到上一次递归的节点后面。
- 正常应该返回原结点即可;
- 若遇到删除节点,则将删除结点的下一个拼接到上一个结点
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的长度,走的长度相同。
特殊情况
- 若有一个链表为NULL,则无交点
- 如下代码中,若两个链表无交点,会进入死循环。通过记录两个链表最后一个结点,判断是否相同,判断两链表有无交点
- 若两个链表长度相同且有公共节点,同时走到最后的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 快慢指针
- 先求两个链表长度,假设相差k个元素。
- 再遍历链表,长链表指针先走k步,然后两个链表遍历指针一起移动,知道结点相同