1.给你两个单链表的头节点 headA 和 headB ,请你找出并返回两个单链表相交的起始节点。如果两个链表不存在相交节点,返回 null 。
这里我们应该想一想如果相交,我们应该通过什么方式来判断?这里我们可以应用类似追击的问题的解决方式来进行答题。
首先这个问题会出现以下的三种情况:
(以上的图片来自力扣)
在追击问题中,两人之间总会是有一些的距离,这个距离会使两人在循环里不停地绕圈,这样不方便我们判断进入循环的入口,所以我们要消除两人之间的距离。
ListNode* getIntersectionNode(ListNode* headA, ListNode* headB)
{
ListNode* head1 = headA;
ListNode* head2 = headB;
int count1 = 1;
int count2 = 1;
int gap;
while (head1)
{
head1 = head1->next;
count1++;
}
while (head2)
{
head2 = head2->next;
count2++;
}
if (count1 > count2)
{
gap = count1 - count2;
while (gap--)
{
headA = headA->next;
}
}
else
{
gap = count2 - count1;
while (gap--)
{
headB = headB->next;
}
}
这样我们就可以在同一个起跑线。
那么下面我们就要判断是否会有相交,如果有我们要确定相交的入口。
while (headA)
{
if (headA == headB)
{
head1 = headA;
return headA;
}
headA = headA->next;
headB = headB->next;
}
return NULL;
为什么要先判断,在进行下一个呢?headA或headB开始就在相交的位置,如果先进行下一步,会使得判断相关的入口下移一个,导致错误。 -
这里便会有人有疑问,为什么不用每一个链表里的数字来进行判断呢?这样不会更简单吗?这是一个错误的想法。
通过这个图片可以看出你的错误的原因。
2. 反转链表
这里我们可以运用三个指针的方式来进行解答。
其实我们只是改变了指针的指向,来进行反转
ListNode* tou(ListNode* head)
{
ListNode* n1 = NULL;
ListNode* n2 = head;
ListNode* n3 = head->next;
while (n2)
{
n2->next = n1;
n1 = n2;
n2 = n3;
if (n3)
n3 = n3->next;
}
return n1;
}
这个箭头便是n2—>next,令他们指向n1,然后使他们往后移,直到n3为NULL时。