1: 从尾到头打印链表
题目:输入一个链表,按链表值从尾到头的顺序返回一个ArrayList。
解析:既然是从尾到头打印链表,那么这种先遍历最后出来的,不正符合栈的结构么?所以使用栈保存这些节点的值即可。
代码:
/**
* struct ListNode {
* int val;
* struct ListNode *next;
* ListNode(int x) :
* val(x), next(NULL) {
* }
* };
*/
class Solution {
public:
vector<int> printListFromTailToHead(ListNode* head)
{
vector<int>vec;
stack<int>st;
ListNode* p = head;
while(p)
{
int val = p->val;
st.push(val);
p = p->next;
}
while(!st.empty())
{
int top = st.top();
vec.push_back(top);
st.pop();
}
return vec;
}
};
2:链表中倒数第k个结点
题目:输入一个链表,输出该链表中倒数第k个结点。
解析:求倒数第k个节点,那么怎么一次遍历搞定呢?可以让平p1指针先走k-1步,然后p1,p2在同步而行,当p1到达尾部时,p2所指的节点就是倒数第k个节点。
在循环的时候,一定注意k,k如果比整个链表的长度还大,那么可能k还没为0,而p早已到了链表的末尾的下一个节点。 我在这里错了好久,没发现。
代码:
/*
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) return NULL;
ListNode* p1 = pListHead;
ListNode* p2 = pListHead;
unsigned int forward_k = k-1;
while(forward_k)
{
p1 = p1->next;
--forward_k;
if(p1==NULL) return NULL;
}
if(!(p1->next)) return p2;
while(p1)
{
p1 = p1->next;
p2 = p2->next;
if(p1->next==NULL) break;
}
return p2;
}
};
3:反转链表
题目:
输入一个链表,反转链表后,输出新链表的表头。
解析:
最开始我觉得可能题目给的链表里应该带头结点,但是后来试了下,没有带头结点,但是一般处理链表的时候都会带头结点,所以我认为的生成一个头结点。反转链表常用的方法是头插法,只要搞清楚指针的指向就行,注意
cur = p; //在这之后,立马应该改变p的值,不然cur头插以后,指针丢掉了。
代码:
/*
struct ListNode {
int val;
struct ListNode *next;
ListNode(int x) :
val(x), next(NULL) {
}
};*/
class Solution
{
public:
ListNode* ReverseList(ListNode* pHead)
{
if(pHead==NULL) return NULL;
ListNode* ppHead = (ListNode*)malloc(sizeof(ListNode));
ppHead->val = 0;
ppHead->next = NULL;
ListNode* p = pHead;
if(!p) return pHead;
ListNode* cur;
while(p)
{
cur = p;
p = p->next;
cur->next = ppHead->next;
ppHead->next = cur;
if(!p) break;
}
return ppHead->next;
}
};
4:合并两个排序的链表
题目描述
输入两个单调递增的链表,输出两个链表合成后的链表,当然我们需要合成后的链表满足单调不减规则。
解析:可以申明一个头结点,然后依次比较两个链表的值,采用尾插法,最后如果p1位空了,那么直接把p2剩余的链表连接在后面即可。反之p2空了也是一样。
非递归版本
代码:
/*
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;
if(pHead2==NULL) return pHead1;
ListNode *p1,*p2;
p1 = pHead1;
p2 = pHead2;
ListNode *pHead = new ListNode(1);
pHead->next = NULL;
ListNode *p = pHead;
while(p1&&p2)
{
ListNode* temp;
int val1 = p1->val;
int val2 = p2->val;
if(val1<=val2)
{
temp = p1;
p1 = p1->next;
}
else
{
temp = p2;
p2 = p2->next;
}
temp->next = NULL;
p->next = temp;
p = temp;
if(p1==NULL||p2==NULL) break;
}
if(!p1) p->next = p2;
else p->next = p1;
return pHead->next;
}
};
递归版本
/*
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;
if(pHead2==NULL) return pHead1;
ListNode* pNewHead = NULL;
if(pHead1->val<=pHead2->val)
{
pNewHead = pHead1;
pNewHead->next = Merge(pHead1->next,pHead2);
}
else
{
pNewHead = pHead2;
pNewHead->next = Merge(pHead1,pHead2->next);
}
return pNewHead;
}
};
5:复杂链表的复制
题目描述:
输入一个复杂链表(每个节点中有节点值,以及两个指针,一个指向下一个节点,另一个特殊指针指向任意一个节点),返回结果为复制后复杂链表的head。(注意,输出结果中请不要返回参数中的节点引用,否则判题程序会直接返回空)
这道题有两种解法。1:使用哈希表。2:在原链表中对每个节点都复制一次。
1:哈希表的方法
首先我们另外建立另外一条相同的链表,暂时将random置为0,然后在建立这个新链表的时候,使用哈希表将对应的节点存起来,map
newNode->random = mp[oldNode->random]
2:复制节点,然后将新旧链分开
在原来链表的基础上,通知个一模一样的节点,然后在这个新链表的基础上,设置random,然后将新旧链表分开。
新旧链表分开具体实现为:
RandomListNode* pNode = pHead;
RandomListNode* pCloneHead = pNode->next;
RandomListNode* pCloneNode = pCloneHead;
pNode->next = pCloneNode->next;
pNode = pCloneNode->next;
while (pNode != NULL)
{
pCloneNode->next = pNode->next;
pCloneNode = pNode->next;
pNode->next = pCloneNode->next;
pNode = pCloneNode->next;
}
完整的调试代码和具体算法代码如下,Clone为哈希的方法,Clone1为复制节点的做法
#include "stdafx.h"
#include<iostream>
#include<vector>
#include<stack>
#include<map>
using namespace std;
struct RandomListNode {
int label;
struct RandomListNode *next, *random;
RandomListNode(int x) :
label(x), next(NULL), random(NULL) {
}
};
RandomListNode* Clone(RandomListNode* pHead)
{
if (pHead == NULL) return NULL;
map<RandomListNode*, RandomListNode*>mpNode;
RandomListNode *cur, *newCur;
RandomListNode* Head = pHead; //新链表的头结点
RandomListNode* newHead = new RandomListNode(Head->label);
mpNode[pHead] = newHead; //将新旧链表的节点对应起来
RandomListNode* p = pHead; //p是对应旧链表的遍历节点
RandomListNode* pNew = newHead;//pNew是对应的新链表的遍历节点
//顺序遍历的时候存储另外一边的节点
while (p->next)
{
cur = p->next;
newCur = new RandomListNode(cur->label);
pNew->next = newCur;
mpNode[cur] = newCur;
pNew = newCur;
p = p->next;
}
pNew = newHead;
cout << pNew->label<<" ";
///////遍历一下
while (pNew->next)
{
cout << pNew->next->label << " ";
pNew = pNew->next;
}
cout << endl << "---------------------------------------" << endl;
p = pHead;
pNew = newHead;
pNew->random = mpNode[p->random];
while (p->next)
{
cur = p->next;
newCur = pNew->next;
newCur->random = mpNode[cur->random];
p = p->next;
pNew = pNew->next;
}
pNew = newHead;
cout << pNew->label << " " << pNew->random->label << " " << endl;;
///////遍历一下
while (pNew->next)
{
cout << pNew->next->label << " ";
if (pNew->next->random != NULL) cout << pNew->next->random->label << " " << endl;
else cout << endl;
pNew = pNew->next;
}
return newHead;
}
RandomListNode* Clone1(RandomListNode* pHead)
{
if (pHead == NULL) return pHead;
RandomListNode* pCur = pHead;
while (pCur != NULL)
{
int val = pCur->label;
RandomListNode* pNode = new RandomListNode(val);
pNode->next = pCur->next;
pCur->next = pNode;
pCur = pCur->next->next;
}
pCur = pHead;
while (pCur != NULL)
{
RandomListNode* pCurNext = pCur->next;
if (pCur->random) pCurNext->random = pCur->random->next;
pCur = pCur->next->next;
}
RandomListNode* pNode = pHead;
RandomListNode* pCloneHead = pNode->next;
RandomListNode* pCloneNode = pCloneHead;
pNode->next = pCloneNode->next;
pNode = pCloneNode->next;
while (pNode != NULL)
{
pCloneNode->next = pNode->next;
pCloneNode = pNode->next;
pNode->next = pCloneNode->next;
pNode = pCloneNode->next;
}
RandomListNode* p = pCloneHead;
while (p != NULL)
{
cout << p->label << " ";
if(p->random) cout<<p->random->label << endl;
else cout << endl;
p = p->next;
}
cout << "------------------------------------" << endl;
p = pHead;
while (p != NULL)
{
cout << p->label << " ";
if (p->random) cout << p->random->label << endl;
else cout << endl;
p = p->next;
}
return pCloneHead;
}
int main()
{
RandomListNode* p1 = new RandomListNode(3);
RandomListNode* p2 = new RandomListNode(5);
RandomListNode* p3 = new RandomListNode(8);
RandomListNode* p4 = new RandomListNode(9);
RandomListNode* p5 = new RandomListNode(100);
p1->next = p2;
p2->next = p3;
p3->next = p4;
p4->next = p5;
p5->random = p1;
p1->random = p2;
p4->random = p3;
//Clone(p1);
Clone1(p1);
return 0;
}