标签:std 部分 NPU 逆序 遍历 etc 边界条件 tps lis
https://leetcode-cn.com/problems/reverse-linked-list/description/
ListNode
给了3个构造函数,明显是方便我们构造结点用的(如果要new,最好要delete)递归算法中有两个重要概念:递归表达式和递归出口,这一点似乎主要是在算法设计与分析课程上学得的。
递归出口
递归出口越小越好,出口应该考虑到边界条件
递归表达式
递归表达式是将链表分为两部分A和B,B用递归表达式递归处理,然后再将A和B“拼接”起来
这一版不太优美,最后一层没用递归(递归应该最大化,出口应该最小化),而是手动实现了就又改了一版,可以再往下看(代码二)。
// Problem: LeetCode 206
// URL: https://leetcode.com/problems/reverse-linked-list/description/
// Tags: Linked List Recursion Iteration
// Difficulty: Easy
#include <iostream>
using namespace std;
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 *reverseList(ListNode *head)
{
// 边界:when there is no node or there is only 1 node, then it‘s no need to reverse,just return the input
if(nullptr == head || nullptr == head->next){
return head;
}
// 递归出口(recursive export),when there are only 2 nodes
if(nullptr == head->next->next){
ListNode *ptrA = head;
ListNode *ptrB = head->next;
ptrB->next = ptrA;
ptrA->next = nullptr;
return ptrB;
}
// 以下为递归表达式
// devide the nodes into A(the original head) and B(the nodes except the original head).
ListNode *ptrA = head; // A:原先的head
ListNode *ptrB = reverseList(head->next); // B:将原先head以外的结点逆序并返回其head
// look for the tail of B,寻找B的尾巴
ListNode* tailB = ptrB;
while (tailB->next != nullptr){tailB = tailB->next;}
// 将A连接到B后面并将A设置为尾结点
tailB->next = ptrA;
ptrA->next = nullptr;
// 返回链表B
return ptrB;
}
};
int main()
{
// system("pause");
return 0;
}
// Problem: LeetCode 206
// URL: https://leetcode.com/problems/reverse-linked-list/description/
// Tags: Linked List Recursion Iteration
// Difficulty: Easy
#include <iostream>
using namespace std;
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 *reverseList(ListNode *head)
{
// 边界:when there is no node, then it‘s no need to reverse,just return the input
if (nullptr == head)
{
return head;
}
// 递归出口(recursive export),when there is only 1 nodes
if (nullptr == head->next)
{
return head;
}
// devide the nodes into A(the original head) and B(the nodes except the original head).
ListNode *ptrA = head; // A:原先的head
ListNode *ptrB = reverseList(head->next); // B:将原先head以外的结点逆序并返回其head
// look for the tail of B,寻找B的尾巴
ListNode *tailB = ptrB;
while (tailB->next != nullptr)
{
tailB = tailB->next;
}
// 将A连接到B后面并将A设置为尾结点
tailB->next = ptrA;
ptrA->next = nullptr;
// 返回链表B
return ptrB;
}
};
int main()
{
// system("pause");
return 0;
}
第二天看了题解之后,发现我自己忽略了一点:
在ListNode *ptrB = reverseList(head->next);
运行后,链表B反转前的第一个结点(即head->next
)已经是链表B反转后的最后一个结点,所以不需要再寻找B的尾结点了。
修改后代码如下:
// Problem: LeetCode 206
// URL: https://leetcode.com/problems/reverse-linked-list/description/
// Tags: Linked List Recursion Iteration
// Difficulty: Easy
#include <iostream>
using namespace std;
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 *reverseList(ListNode *head)
{
// 边界:when there is no node, then it‘s no need to reverse,just return the input
if (nullptr == head)
{
return head;
}
// 递归出口(recursive export),when there is only 1 nodes
if (nullptr == head->next)
{
return head;
}
// devide the nodes into A(the original head) and B(the nodes except the original head).
ListNode *ptrA = head; // A:原先的head
ListNode *ptrB = reverseList(head->next); // B:将原先head以外的结点逆序并返回其head,此时head->next已经为最后一个结点
// 将A连接到B后面并将A设置为尾结点
head->next->next = ptrA;
ptrA->next = nullptr;
// 返回链表B
return ptrB;
}
};
int main()
{
// system("pause");
return 0;
}
其实就是头插法,另外要注意这道题里中链表的头结点的val是有意义的,所以最后要new出来的头结点delete掉,并返回其next。
这份代码是没有修改原链表的结构的,而是基于原链表new了一个新链表(是原链表的逆序)
// Problem: LeetCode 206
// URL: https://leetcode.com/problems/reverse-linked-list/description/
// Tags: Linked List Recursion Iteration
// Difficulty: Easy
#include <iostream>
using namespace std;
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 *reverseList(ListNode *head)
{
// 创建新链表
ListNode* newHead = new ListNode(-1);
while (head != nullptr){
ListNode *tempNodePtr = new ListNode(head->val, head->next);
tempNodePtr->next = newHead->next;
newHead->next = tempNodePtr;
// 取下一个结点
head = head->next;
}
// 释放无用的头结点并返回真正的头结点
ListNode* ret = newHead->next;
delete newHead;
return ret;
}
};
int main()
{
// system("pause");
return 0;
}
这份代码修改了原链表的结构,直接利用了原链表的结点
// Problem: LeetCode 206
// URL: https://leetcode.com/problems/reverse-linked-list/description/
// Tags: Linked List Recursion Iteration
// Difficulty: Easy
#include <iostream>
using namespace std;
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 *reverseList(ListNode *head)
{
// 创建新链表
ListNode* newHead = new ListNode(-1);
while (head != nullptr){
ListNode* next = head->next;
head->next = newHead->next;
newHead->next = head;
// 取下一个结点
head = next;
}
// 释放无用的头结点并返回真正的头结点
ListNode* ret = newHead->next;
delete newHead;
return ret;
}
};
int main()
{
// system("pause");
return 0;
}
作者:@臭咸鱼
转载请注明出处:https://www.cnblogs.com/chouxianyu/
欢迎讨论和交流!
标签:std 部分 NPU 逆序 遍历 etc 边界条件 tps lis
原文地址:https://www.cnblogs.com/chouxianyu/p/13284071.html