活动地址:CSDN21天学习挑战赛
将两个升序链表合并为一个新的 升序 链表并返回。新链表是通过拼接给定的两个链表的所有节点组成的。
示例 1:
**输入:**l1 = [1,2,4], l2 = [1,3,4] 输出:[1,1,2,3,4,4]
示例 2:
**输入:**l1 = [ ], l2 = [ ] 输出:[ ]
示例 3:
**输入:**l1 = [ ], l2 = [0] 输出:[0]
提示:
核心代码模式
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* struct ListNode *next;
* };
*/
struct ListNode* mergeTwoLists(struct ListNode* list1, struct ListNode* list2)
{
}
思路其实很简单,这里用了哨兵结点作为新链表的头结点,用两个指针把两个链表中的结点互相比较,小的先尾插到新链表中,总会有一条链表先插完,没插完的链表把剩下的结点一次尾插到新链表。有一些要注意的点,首先创建了哨兵结点,定义了guard指针指向哨兵结点,这时应该立即给哨兵结点的next指针初始化为NULL,不然有野指针的潜在风险。定义两个指针cur1和cur2分别对应list1链表和list2链表,while循环的条件应当是cur1&&cur2
,为什么呢?这样的话只要有一个链表先插完就立马跳出循环。在循环结束后要根据哪个链表还没插完,把剩余结点全部尾插到新链表。我们这里使用的辅助结点——哨兵结点是题目没提供的,我们应当在最后将其释放,不过释放前得先把哨兵结点的next指针的内容取出来,作为头指针返回。
代码实现
struct ListNode* mergeTwoLists(struct ListNode* list1, struct ListNode* list2)
{
struct ListNode* cur1 = list1;
struct ListNode* cur2 = list2;
struct ListNode* guard = (struct ListNode*)malloc(sizeof(struct ListNode));
guard->next = NULL;
struct ListNode* tail = guard;
while(cur1 && cur2)
{
if(cur1->val > cur2->val)
{
tail->next = cur2;
tail = tail->next;
cur2 = cur2->next;
}
else
{
tail->next = cur1;
tail = tail->next;
cur1 = cur1->next;
}
}
if(cur1)
tail->next = cur1;
if(cur2)
tail->next = cur2;
struct ListNode* head = guard->next;
free(guard);
return head;
}
给你单链表的头节点 head ,请你反转链表,并返回反转后的链表。
链接:Leetcode206
示例
示例 1:
**输入:**head = [1,2,3,4,5] 输出:[5,4,3,2,1]
示例 2:
**输入:**head = [1,2] 输出:[2,1]
示例 3:
**输入:**head = [] 输出:[]
提示:
核心代码模式
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* struct ListNode *next;
* };
*/
struct ListNode* reverseList(struct ListNode* head)
{
}
实际上有一道题和这个基本一样,只是要求的是使用数组,而这里使用的是单链表。思路也是可以借鉴互通的,不妨创建一个新的链表,不过相比于数组,这里不需要开辟新结点,只是把结点间的指向关系进行修改。定义一个新的头指针newHead,定义一个查找当前结点的cur指针,查找下一结点的next指针,只要cur不指向NULL,就把cur指向的结点放到新链表去,怎么放呢?把newHead的内容给cur指向结点的next指针,让它指向newHead原来指向的东西,再把cur指向结点的地址给newHead,让newHead指向该结点,不过要注意在执行这些操作之前要先把cur->next的值放到next去,在执行完后要把next的值再放到cur去。其实也就是让原来的结点从前向后一个一个头插到新链表中。
代码实现
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;
}
有没有想过这样一种方法,既然链表是通过指针联系的,那把指针指向关系逆转了不就能实现反转了吗,用三个指针,分别指向前一结点、当前结点和下一结点(prev、cur、next),只要cur指向不为NULL,就说还有结点没有反转,就把前一结点的地址赋给cur指向的当前结点的next指针,让它指向前一结点,然后三个指针都向后移动一位,不断循环至cur指向NULL。反转后的新链表的头结点由prev指向,返回prev即可。
代码实现
struct ListNode* reverseList(struct ListNode* head)
{
struct ListNode* prev = NULL;
struct ListNode* cur = head;
struct ListNode* next = NULL;
while(cur)
{
next = cur->next;
cur->next = prev;
prev = cur;
cur = next;
}
return prev;
}