题目:输入一个链表,按链表值从尾到头的顺序返回一个ArrayList。
看到这个题目,相信大家脑海里会有很多想法,今天主要在这里说三种它的实现方法。
利用栈实现逆置
我们都知道栈遵循先进后出的原则,所以当我们面对逆置问题时,最先想到的应该就是利用栈来实现,原理如下图所示:
我们对链表进行遍历将其各个节点依次入栈,遍历完成后,再依次出栈,将其放入容器中,完成逆置。
代码如下:
class Solution {
public:
vector<int> printListFromTailToHead(ListNode* head) {
vector<int> con;
if(head == nullptr) return con;
ListNode *p = head;
stack<int> st;
while(p!= nullptr)
{
st.push(p->val);
p= p->next;
}
while(!st.empty())
{
con.push_back(st.top());
st.pop();
}
return con;
}
};
我们发现这样除了必要的容器之外还要给栈开辟空间,造成的一定的空间损失,那么有没有什么办法可以不借用栈来实现链表逆置呢?我们在寻找一种方法可以在将节点放入容器的过程中完成逆置,这个时候头插法就有了用处。
利用头插法
相信这个大家很容易理解,它的实现原理如图所示:
首先我们定义一个容器value用于存放新的链表:
我们将原链表依次遍历利用头插法将其放入value中,如下图所示:
当我们将head所指节点数值放入新容器之后,head指向下一个节点,重复此操作知道head指向空值,遍历结束,最后我们将valud返回就好。
下面是我们的实现代码:
class Solution {
public:
vector<int> printListFromTailToHead(ListNode* head) {
vector<int> value;
if(head==nullptr) return value;
else
{
while(head!=nullptr)
{
value.insert(value.begin(),head->val);
head=head->next;
}
}
return value;
}
};
但是这样做有一个弊端,我们直接使用head遍历会破环原来的链表,所以我们可以对上面的代码进行稍微的改变,重新定义一个指针指向头结点完成遍历,这个很简单就不再写代码了。
利用reverse()实现
reverse()函数可以实现容器内容的反转,所以我们只需要在将链表遍历存入容器后,调用reverse()函数将内容逆置就好。代码可以参考下面的:
class Solution {
public:
vector<int> printListFromTailToHead(ListNode* head) {
vector<int> con;
if(head == nullptr) return con;
ListNode *p = head;
while(p!= nullptr)
{
con.push_back(p->val);
p= p->next;
}
reverse(con.begin(),con.end());
return con;
}
};