题目一:输入一个链表,从尾到头打印链表每个节点的值。
采用c++:
方法一:开辟栈空间,将链表从头到尾放入栈中,然后再打印栈代码如下:
/**
* struct ListNode {
* int val;
* struct ListNode *next;
* ListNode(int x) :
* val(x), next(NULL) {
* }
* };
*/
class Solution {
public:
vector<int> printListFromTailToHead(ListNode* head) {
//从尾到头将结果先放入栈中,然后输出栈,实现不改变链表的结构从尾到头输出
std::stack<ListNode *> nodes;
ListNode *Phead = head;
vector<int> vec;
while(Phead != NULL)
{
nodes.push(Phead);
Phead = Phead->next;
}
while(!nodes.empty()){
Phead = nodes.top();
vec.push_back(Phead->val);
nodes.pop();
}
return vec;
}
};
由于递归的本质就是一个栈结构,想到用栈实现,所以用递归也可以实现,访问每个结点时,先递归输出它后面的结点,再输出该结点自身,这样链表的输出结果就会反过来。
代码如下:
vector<int> vec;
vector<int> printListFromTailToHead(ListNode* head) {
if(head == NULL) return vec;
printListOfRecursion(head);
return vec;
}
void printListOfRecursion(ListNode* head)
{
if(head != NULL)
{
if(head->next != NULL)
{
printListFromTailToHead(head->next);
}
vec.push_back(head->val);
}
}
题目二: 输入一个链表,输出该链表中倒数第k个结点
解题思路:此题可以利用上一题的解题思路,将链表先放入栈中,然后输出栈中的第k个值
栈结构如下所示:
struct ListNode {
int val;
struct ListNode *next;
ListNode(int x) :
val(x), next(NULL) {
}
};
代码如下所示:
class Solution {
public:
ListNode* FindKthToTail(ListNode* pListHead, unsigned int k) {
//先放入栈中,然后再输出栈中第k个值就是链表中的倒数第k个值
stack<ListNode *> FindKthStack;
int flag = 0;
while(pListHead != NULL)
{
FindKthStack.push(pListHead);
pListHead = pListHead->next;
flag++;
}
if(flag < k || k == 0) //边界问题,没有考虑当为k==0 或者 链表的长度小于k的值,思考了好久的问题,思路没有错误,但是在细节上没有考虑到
{
return NULL;
}
for(int i = 1;i <= (k - 1);i++)
{
if(!FindKthStack.empty())
FindKthStack.pop();
}
return FindKthStack.top();
}
};
vector<ListNode *> FindKthVector;
while(pListHead)
{
FindKthVector.push_back(pListHead);
pListHead = pListHead->next;
}
if(FindKthVector.size() < k || k == 0 )
return NULL;
return FindKthVector[FindKthVector.size()-k];
1、定义两个指针L1,L2 ;
2、先让L2走k-1步;
3、然后L1,L2同时走直至L2走到链表尾端为止,则L1现在所指的指针就是倒数第k个指针
具体代码如下:
ListNode *L1 = pListHead,*L2 = pListHead;
unsigned int i = 0;
if(pListHead == NULL || k == 0)
{
return NULL;
}
for(int i = 0;i < k-1;i++)
{
if(L2->next == NULL){return NULL;}
else{ L2 = L2->next; }
}
while(L2->next != NULL)
{
L1 = L1->next;
L2 = L2->next;
}
return L1;
题目三: 输入一个链表,反转链表后,输出链表的所有元素。
解题思路:定义三个指针,头pre,尾 nail 和中间指针 cur
核心代码就4句话:
nail = cur->next;
cur->next = pre;
pre = cur;
cur = nail;
尾指针先保存中间指针的下一个结点,然后将前指针赋值给中间指针的下一个结点,这两步实现指针指向的逆转;
后面两句话分别让前指针和中间指针往后移一步,实现遍历整个链表;
完整代码如下:
class Solution {
public:
ListNode* ReverseList(ListNode* pHead) {
if(pHead == NULL)
{
return NULL;
}
//定义三个指针,nail表示正方向的下一个指针,pre表示反向的下一个指针,cur表示中间的指针
ListNode* pre,*cur,*nail;
pre = pHead;
cur = pHead->next;
while(cur){
nail = cur->next;
cur->next = pre;
pre = cur;//反向的指针前进一个
cur = nail; //正向的指针前进一个
}
pHead->next = NULL;//pHead变成尾指针
pHead = pre; //pre为头指针赋值给pHead
return pHead;
}
};
题目四:合并两个排序的链表
输入两个单调递增的链表,输出两个链表合成后的链表,当然我们需要合成后的链表满足单调不减规则。
可以选择递归和非递归的调用方法,递归方法比较简单也很好理解
递归方法:使用递归方法,首先要想好结束条件
class Solution {
public:
ListNode* Merge(ListNode* pHead1, ListNode* pHead2)
{
if(pHead1 == NULL && pHead2 != NULL){ return pHead2;} //边界问题,要考虑清楚
else if(pHead1 != NULL && pHead2 == NULL){ return pHead1;}//边界问题,要考虑清楚
else if(pHead1 == NULL && pHead2 == NULL){ return NULL;} //边界问题,要考虑清楚
//递归调用判断连个链表哪个是最小值,然后赋值给mergeList的下一个值,这个函数利用递归很好理解
ListNode * mergeList;
if(pHead2->val < pHead1->val)
{
mergeList = pHead2;
pHead2 = pHead2->next;
mergeList->next = Merge(pHead1,pHead2);
}
else
{
mergeList = pHead1;
pHead1 = pHead1->next;
mergeList->next = Merge(pHead1,pHead2);
}
return mergeList;
}
};
非递归方法:考虑比较多一点,首先要判断头结点,然后循环中间结点,然后对尾结点进行赋值
class Solution {
public:
ListNode* Merge(ListNode* pHead1, ListNode* pHead2)
{
if(pHead1 == NULL && pHead2 != NULL){ return pHead2;} //边界问题,要考虑清楚
else if(pHead1 != NULL && pHead2 == NULL){ return pHead1;}//边界问题,要考虑清楚
else if(pHead1 == NULL && pHead2 == NULL){ return NULL;} //边界问题,要考虑清楚
//非递归方法
ListNode* pHead = NULL;
ListNode* pre = NULL;
//取较小的值作头节点
if(pHead2->val <= pHead1->val)
{
pre = pHead2;
pHead2 = pHead2->next;
}
else
{
pre = pHead1;
pHead1 = pHead1->next;
}
//开始遍历合并
pHead = pre;
while(pHead1 != NULL && pHead2 != NULL )
{
if(pHead2->val <= pHead1->val)
{
pHead->next = pHead2;
pHead2 = pHead2->next;
pHead = pHead->next;
}
else
{
pHead->next = pHead1;
pHead1 = pHead1->next;
pHead = pHead->next;
}
}
//判断是否到了尾端
if(pHead1 == NULL)
{
pHead->next = pHead2;
}
if(pHead2 == NULL)
{
pHead->next = pHead1;
}
return pre;
}
};