- 剑指 Offer 06: 从尾到头打印链表(easy)
- 剑指 Offer 22. 链表中倒数第k个节点(easy)">剑指 Offer 22. 链表中倒数第k个节点(easy)
- 剑指 Offer 24. 反转链表(easy)">剑指 Offer 24. 反转链表(easy)
- 剑指 Offer 25. 合并两个排序的链表(easy)">剑指 Offer 25. 合并两个排序的链表(easy)
- 剑指 Offer 35. 复杂链表的复制(medium)">剑指 Offer 35. 复杂链表的复制(medium)
剑指 Offer 06: 从尾到头打印链表(easy)
输入一个链表的头节点,从尾到头反过来返回每个节点的值(用数组返回)。
示例 1:
输入:head = [1,3,2]
输出:[2,3,1]
限制:
0 <= 链表长度 <= 10000
方法一 用栈解决
通常,这种情况下,我们不希望修改原链表的结构。返回一个反序的链表,这就是经典的“后进先出”
我们可以使用栈实现这种顺序。每经过一个结点的时候,把该结点放到一个栈中。当遍历完整个链表后,再从栈顶开始逐个输出结点的值,给一个新的链表结构,这样链表就实现了反转。
- 创建一个栈,用于存储链表的节点
- 创建一个指针,初始时指向链表的头节点
- 当指针指向的元素非空时,重复下列操作:
- 将指针指向的节点压入栈内
- 将指针移到当前节点的下一个节点
/*** struct ListNode {* int val;* struct ListNode *next;* ListNode(int x) :* val(x), next(NULL) {* }* };*/class Solution {public:vector<int> printListFromTailToHead(ListNode* head) {stack<int> nodes;vector<int> result;ListNode* node = head;while(node != NULL){nodes.push(node->val);node = node->next;}while(!nodes.empty()){result.push_back(nodes.top());nodes.pop();}return result;}};
剑指 Offer 22. 链表中倒数第k个节点(easy)
输入一个链表,输出该链表中倒数第k个节点。为了符合大多数人的习惯,本题从1开始计数,即链表的尾节点是倒数第1个节点。例如,一个链表有6个节点,从头节点开始,它们的值依次是1、2、3、4、5、6。这个链表的倒数第3个节点是值为4的节点。
示例:
给定一个链表: 1->2->3->4->5, 和 k = 2.
返回链表 4->5.
方法一 双指针
算法流程:
- 初始化: 前指针 former 、后指针 latter ,双指针都指向头节点 head 。
- 构建双指针距离: 前指针 former 先向前走 k 步(结束后,双指针 former 和 latter 间相距 k 步)。
- 双指针共同移动: 循环中,双指针 former 和 latter 每轮都向前走一步,直至 former 走过链表 尾节点 时跳出(跳出后, latter 与尾节点距离为 k−1,即 latter 指向倒数第 l 个节点)。
- 返回值: 返回 latter 即可。
/*struct ListNode {int val;struct ListNode *next;ListNode(int x) :val(x), next(NULL) {}};*/class Solution {public:ListNode* FindKthToTail(ListNode* pListHead, unsigned int k) {if(pListHead == NULL || k == 0){return NULL;}ListNode *pAhead = pListHead;ListNode *pBehind = pListHead;for(unsigned int i = 0; i < k - 1; i++){if(pAhead->next != NULL){pAhead = pAhead->next;}else{return NULL;}}while(pAhead->next != NULL){pAhead = pAhead->next;pBehind = pBehind->next;}return pBehind;}};
剑指 Offer 24. 反转链表(easy)
方法一 替换节点
这个很简单,我们使用三个指针,分别指向当前遍历到的结点、它的前一个结点以及后一个结点。
在遍历的时候,做当前结点的尾结点和前一个结点的替换。
/*struct ListNode {int val;struct ListNode *next;ListNode(int x) :val(x), next(NULL) {}};*/class Solution {public:ListNode* ReverseList(ListNode* pHead) {ListNode* pReversedHead = NULL;ListNode* pNode = pHead;ListNode* pPrev = NULL;while(pNode != NULL){ListNode* pNext = pNode->next;if(pNext == NULL){pReversedHead = pNode;}pNode->next = pPrev;pPrev = pNode;pNode = pNext;}return pReversedHead;}};
剑指 Offer 25. 合并两个排序的链表(easy)

方法一 递归连接
先判断输入的链表是否为空的指针。如果第一个链表为空,则直接返回第二个链表;如果第二个链表为空,则直接返回第一个链表。如果两个链表都是空链表,合并的结果是得到一个空链表。
两个链表都是排序好的,我们只需要从头遍历链表,判断当前指针,哪个链表中的值小,即赋给合并链表指针即可。使用递归就可以轻松实现
/*struct ListNode {int val;struct ListNode *next;ListNode(int x) :val(x), next(NULL) {}};*/class Solution {public:ListNode* Merge(ListNode* pHead1, ListNode* pHead2){//判断指针是否为空if(pHead1 == NULL){return pHead2;}else if(pHead2 == NULL){return pHead1;}ListNode* pMergedHead = NULL;if(pHead1->val < pHead2->val){pMergedHead = pHead1;pMergedHead->next = Merge(pHead1->next, pHead2);}else{pMergedHead = pHead2;pMergedHead->next = Merge(pHead1, pHead2->next);}return pMergedHead;}};
剑指 Offer 35. 复杂链表的复制(medium)

