1、反转链表
问题描述
反转一个单链表。
示例:
输入: 1->2->3->4->5->NULL
输出: 5->4->3->2->1->NULL
代码实现
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode(int x) : val(x), next(NULL) {}
* };
*/
class Solution {
public:
ListNode* reverseList(ListNode* head) {
if(head == NULL)
return NULL;
if(head->next == NULL)
return head;
ListNode* p = reverseList(head->next); // p最终指向了尾结点
head->next->next = head; // 向回指向
head->next = NULL; // 原来顺序的指针断掉
return p; // 返回最为顺序指向尾结点指针 此时作为头指针的p指针
}
};
运行截图
非递归(迭代)写法
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode(int x) : val(x), next(NULL) {}
* };
*/
class Solution {
public:
ListNode* reverseList(ListNode* head) {
if(head == NULL)
return NULL;
ListNode* pcur = head, *pnext = pcur->next;
pcur->next = nullptr;
while(pnext){
ListNode* ptmp = pcur;
pcur = pnext;
pnext = pnext->next;
pcur->next = ptmp;
}
return pcur;
}
};
运行截图
2、反转链表 II
问题描述
反转从位置m
到n
的链表。请使用一趟扫描完成反转。
说明:
1 ≤ m ≤ n ≤ 链表长度
。
示例:
输入: 1->2->3->4->5->NULL, m = 2, n = 4
输出:1->4->3->2->5->NULL
解题思路
用善意题目迭代的方法,但要注意分两种情况讨论:(1)m == 1
时,需要改动头指针;(2)m != 1
时,无需改动头指针。
算法实现
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode(int x) : val(x), next(NULL) {}
* };
*/
class Solution {
//建立伪头结点
public:
ListNode* reverseBetween(ListNode* head, int m, int n) {
if(head->next == nullptr)
return head;
ListNode* h = new ListNode(0);
h->next = head;
ListNode* p = h;
head = nullptr;
int i = 1;
for(; i < m; i++)
p = p->next; // 让p指向m的前一个结点
ListNode* pbegin = p->next, *pcur = pbegin, *pend = pcur->next;
for(; i < n; i++){
ListNode* ptmp = pcur;
pcur = pend;
pend = pend->next;
pcur->next = ptmp;
}
p->next = pcur;
pbegin->next = pend;
return h->next;
}
};
运行截图
3、合并两个有序链表
问题描述
将两个升序链表合并为一个新的 升序 链表并返回。新链表是通过拼接给定的两个链表的所有节点组成的。
示例:
输入:1->2->4, 1->3->4
输出:1->1->2->3->4->4
解题思路
- 链表的兼并是老生常谈的问题,却总是费时间完成。对于不带头结点的链表来说,需要建立一个伪头结点作为合并链表后的头结点。
- 考虑其中一个链表为空的情况,直接返回另一个链表。
- 定义两个动态指针指向两个链表表头,设置
tail
指针作为尾插法的尾指针。 - 比较两个动态指针所指向结点值的大小,较小的值是待插入结点,方法就是尾插法。
代码实现
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode() : val(0), next(nullptr) {}
* ListNode(int x) : val(x), next(nullptr) {}
* ListNode(int x, ListNode *next) : val(x), next(next) {}
* };
*/
class Solution {
public:
ListNode* mergeTwoLists(ListNode *a, ListNode *b) {
if (a == nullptr or b == nullptr)
return a ? a : b;
ListNode head, *tail = &head, *aPtr = a, *bPtr = b;
while (aPtr and bPtr) {
if (aPtr->val < bPtr->val) {
tail->next = aPtr;
aPtr = aPtr->next;
}
else{
tail->next = bPtr;
bPtr = bPtr->next;
}
tail = tail->next;
}
tail->next = (aPtr ? aPtr : bPtr);
return head.next;
}
};