第一题
代码如下,主要分为两部分,检查删除部分和迭代部分,删除部分要注意第一个元素为删除的情况。
struct ListNode* removeElements(struct ListNode* head, int val){
struct ListNode* p = NULL,* cur = head;
while(cur)
{
//1.头删 2.中间删除(与尾删相同)
if(cur->val==val)
{
if(cur==head)
{
head=cur->next;
free(cur);
cur = head;
}
else
{
p->next=cur->next;
free(cur);
cur=p->next;
}
}
else
{
//迭代往后走
p=cur;
cur=cur->next;
}
}
return head;
}
第二题
这里有两种解法,第一种是直接用三个指针n1 n2 n3翻转链表, n1为空,n2为第1个节点,n3为n2的后一个节点,首先如果链表为空,则直接返回NULL,翻转环节判断n2是否为NULL,是则退出循环,不是则让n2指向n1,然后往后迭代,要注意n3的迭代可能会出现问题,所以要多加一个条件判断。
struct ListNode* reverseList(struct ListNode* head)
{
if(head == NULL)
return NULL;
struct ListNode *n1 , *n2, *n3;
n1 = NULL;
n2 = head;
n3 = head->next;
while(n2)
{
//翻转
n2->next = n1;
//迭代往后走
n1 = n2;
n2 = n3;
//最后一个节点
if(n3)
n3 = n3->next;
}
return n1;
}
另一种解法,头插法,将节点一个一个重新串起来。
struct ListNode* reverseList(struct ListNode* head)
{
struct ListNode* cur = head;
struct ListNode* newhead = NULL;
while(cur)
{
struct ListNode*next = cur- >next;
/头插
cur->next = newhead;
newhead = cur;
//迭代往后走
cur = next;
}
return newhead;
}
第三题
这里相比遍历一遍链表确定长度以后找出中间节点,用快慢指针的解法更加便利简洁,让快指针一下走两步,慢指针一下一步,当快指针为空或快指针的next为空循环停止,此时慢指针的位置即为中间结点的位置。
struct ListNode *slow, *fast;
slow = fast = head;
while(fast && fast->next)
{
slow = slow->next;
fast = fast->next->next;
}
return slow;
第四题
题解如下
struct ListNode* mergeTwoLists(struct ListNode* list1, struct ListNode* list2){
//如果其中一个链表为空,返回另一个
if(list1 == NULL)
return list2;
if(list2 == NULL)
return list1;
struct ListNode* head=NULL,*tail=NULL;
while(list1 && list2)
{
if(list1->val < list2->val)
{
if( head == NULL)
{
head = tail = list1;
}
else
{
tail->next = list1;
tail = list1;
}
list1 = list1->next;
}
else
{
if(head == NULL)
{
head = tail = list2;
}
else
{
tail->next = list2;
tail=list2;
}
list2=list2->next;
}
}
if(list1)
{
tail->next=list1;
}
if(list2)
{
tail->next=list2;
}
return head;
}
第五题
这里可以依次用A链表的节点与B链表的所有节点进行比较,找到中间节点,但时间复杂度为O(n^2),较为繁琐,这里另一种方法解题,先遍历两个链,计算出长度,并判断两个最后的结点是否相同,如果相同,则他们是相交的,如果不同则不相交,并return NULL,然后让长链表走长度差,这样两个链表到相同节点的中间的节点数就一样了,只要同时往后走,就可以遇到相同节点。
struct ListNode *getIntersectionNode(struct ListNode *headA, struct ListNode *headB) {
struct ListNode* tailA = headA;
struct ListNode* tailB = headB;
int lenA = 1;
while(tailA->next)
{
++lenA;
tailA = tailA->next;
}
int lenB = 1;
while(tailB->next)
{
lenB++;
tailB = tailB->next;
}
if(tailA != tailB)
{
return NULL;
}
int gap = abs( lenA - lenB);
//长的先走差距步,再同时走找交点
struct ListNode* longList = headA;
struct ListNode* shortList = headB;
if( lenA < lenB)
{
shortList = headA;
longList = headB;
}
while(gap--)
{
longList = longList->next;
}
while( longList != shortList)
{
longList = longList->next;
shortList = shortList->next;
}
return longList;
}