1.JZ3 从尾到头打印链表
题目描述:
输入一个链表,按链表从尾到头的顺序返回一个ArrayList。
思路一:如果是从尾到头打印链表,我们自然想到可以使用栈存储节点值,然后倒序打印。
class Solution {
public:
vector<int> printListFromTailToHead(ListNode* head) {
vector<int> result;
stack<int> arr;
ListNode* p=head;
while(p!=NULL)
{
arr.push(p->val);
p=p->next;
}
while(!arr.empty())
{
result.push_back(arr.top());
arr.pop();
}
return result;
}
};
思路二:可以原地反转链表,然后反转后的顺序打印链表。需要注意的是,原地反转链表需要借助额外两个节点指针,需要特别注意的是节点反转指针的顺序遵从“由后往前”的次序。
class Solution {
public:
vector<int> printListFromTailToHead(struct ListNode* head) {
vector<int> res;
ListNode *cur=head;
ListNode *pre=cur;
if(head==NULL)
return res;
while(head->next!=NULL){
//将cur节点移到pre节点之前
cur=head->next;
head->next=cur->next;
cur->next=pre;
pre=cur;
}
while(cur){
res.push_back(cur->val);
cur=cur->next;
}
return res;
}
};
2.JZ14 链表中倒数第k个结点
题目描述:
输入一个链表,输出该链表中倒数第k个结点。
思路一:暴力法
先遍历整个链表,统计节点个数n(从1开始),然后从头遍历链表,输出第n-k-1个节点就是结果。
思路二:双指针法
先让一个指针走上k步,此时当前指针距离链表尾部距离为n-k,然后让另一个指针从头开始两个指针同时走,当指针一到达尾部时,指针二距离尾部为n-(n-k)= k,即倒数第k个结点。
class Solution {
public:
ListNode* FindKthToTail(ListNode* pListHead, unsigned int k) {
//p1指针先遍历k个节点,pListHead再从头开始
ListNode* p1=pListHead;
for(int i=0;i<k;i++)
if(!p1)
return nullptr;
else
p1=p1->next;
while(p1){
p1=p1->next;
pListHead=pListHead->next;
}
return pListHead;
}
};
3.JZ15 反转链表 链表
题目描述:
输入一个链表,反转链表后,输出新链表的表头。
思路一:原地反转。与第一题非常类似,只是输出反转后的表头。
class Solution {
public:
ListNode* ReverseList(ListNode* pHead) {
if(pHead == NULL || pHead->next == NULL)
{
return pHead;
}
ListNode* pre = NULL;
ListNode* after = NULL;
while(pHead)
{
//此处顺序需要弄清楚,先后再前
after = pHead->next; //after最多为空
pHead->next = pre;
pre = pHead;
pHead = after;
}
return pre;
}
};
思路二:使用栈存储结点,利用栈的先入后出顺序。与第一题非常类似,只是输出反转后的表头。
class Solution {
public:
ListNode* ReverseList(ListNode* pHead) {
if(pHead == NULL || pHead -> next == NULL)
return pHead;
ListNode* p = pHead;
stack<ListNode