题目1描述:
1 2 3 4 5 6 7 8
| 输入一个链表的头节点,从尾到头反过来打印出每个节点的值
链表节点定义如下: struct ListNode {
int m_nKey; ListNode* m_pNext; };
|
解法1:反转链表
看到这道题后,很多人的第一反应是将链表中链接节点的指针反转过来,改变链表的方向,然后就可以从头到尾输出了,但该方法会改变原来链表的结构,是否允许在打印链表的时候修改链表的结构?这取决于面试官的要求,因此在面试的时候我们要询问清楚面试官的要求。
⭐️在面试中,如果我们打算修改输入的数据,最好先问面试官是不是允许修改
解法2:栈
通常打印是一个只读操作,我们不希望打印时修改内容,假设面试官也要求这个题目不能改变链表的结构
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
|
void PrintListReversingly_Iteratively(ListNode* pHead) { std::stack<ListNode*> nodes;
ListNode* pNode = pHead; while(pNode != nullptr) { nodes.push(pNode); pNode = pNode->m_pNext; }
while(!nodes.empty()) { pNode = nodes.top(); printf("%d\t", pNode->m_nValue); nodes.pop(); } }
|
解法3:递归
递归在本质上就是一个栈结构,于是我们又想到了用递归来实现
1 2 3 4 5 6 7 8 9 10 11 12 13
| void PrintListReversingly_Recursively(ListNode* pHead) { if(pHead != nullptr) { if (pHead->m_pNext != nullptr) { PrintListReversingly_Recursively(pHead->m_pNext); } printf("%d\t", pHead->m_nValue); } }
|
⭐️递归的代码很简洁,但有一个问题:当链表非常长的时候,就会导致函数调用的层级很深,从而有可能导致函数调用栈溢出,显然用栈基于循环实现的代码鲁棒性要好一些
题目2描述:
1 2 3 4 5 6 7 8
| 输入一个链表的头节点,从尾到头反过来返回每个节点的值(用数组返回)。
示例 1: 输入:head = [1,3,2] 输出:[2,3,1]
限制:0 <= 链表长度 <= 10000
|
解法1:递归
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29
|
class Solution {
vector<int> res;
public: vector<int>& reversePrint(ListNode* head) { if (head == NULL) { return res; }
reversePrint(head -> next); res.push_back(head -> val);
return res; } };
|
解法2:栈
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32
|
class Solution { public: vector<int> reversePrint(ListNode* head) {
stack<int> nodes; vector<int> res;
ListNode* pNode = head;
while(pNode != NULL) { nodes.push(pNode->val); pNode = pNode->next; }
while(!nodes.empty()) { res.push_back(nodes.top()); nodes.pop(); }
return res; } };
|