题目描述
输入一个链表,从尾到头打印链表每个节点的值。
思路1:递归
当head -> next == NULL 时,终止递归返回上层,并将当前节点值压入vector中;最后返回整个vect。
class Solution {
public:
vector<int> printListFromTailToHead(ListNode* head) {
vector<int> res;
if(head!=NULL){
res = printListFromTailToHead(head->next);
res.push_back(head->val);
}
return res;
}
};
缺点: 当链表非常长时,会导致函数调用的层数很深,从而有可能导致栈溢出。
思路2:非递归
使用vector, 遍历的值放在vector首部。
class Solution {
public:
vector<int> printListFromTailToHead(ListNode* head) {
vector<int> ret;
while(head != nullptr)
{
ret.insert(ret.begin(),head->val);
head = head->next;
}
return ret;
}
};
缺点: 每次在vector头部插入数据,会导致函数执行效率很低
思路3:使用vector 正向存储,再reverse
class Solution {
public:
vector<int> printListFromTailToHead(ListNode* head) {
vector<int> ret;
while(head != nullptr)
{
ret.push_back(head->val);
head = head->next;
}
reverse(ret.begin(),ret.end());
return ret;
}
};
思路4:使用栈作为辅助,第一次遍历时,将值压入栈中,整个链表全部压入后再逐一从栈顶输出节点的值。
class Solution {
public:
vector<int> printListFromTailToHead(ListNode* head) {
vector<int> res;
stack<int> temp;
ListNode* p=head;
while(p){
temp.push(p->val);
p = p->next;
}
while(!temp.empty()){
res.push_back(temp.top());
temp.pop();
}
return res;
}
};
题目描述
输入一个链表,输出该链表中倒数第k个结点。
思路1:使用stack存储全部节点,再出栈k-1个,此时栈顶那个就是第k个
class Solution {
public:
ListNode* FindKthToTail(ListNode* pListHead, unsigned int k) {
if(pListHead==NULL||k<=0)
return NULL;
stack temp;
ListNode* p=pListHead;
while(p!=NULL){
temp.push(p);
p=p->next;
}
if(temp.size()return NULL;
for(int i=0; i1; i++){
temp.pop();
}
return temp.top();
}
};
缺点:空间复杂度过高,可能造成栈溢出;
思路2:两个指针,先让第一个指针和第二个指针都指向头结点,然后再让第一个指正走(k-1)步,到达第k个节点。然后两个指针同时往后移动,当第一个结点到达末尾的时候,第二个结点所在位置就是倒数第k个节点了。
class Solution {
public:
ListNode* FindKthToTail(ListNode* pListHead, unsigned int k) {
if(pListHead == NULL || k <= 0)
return NULL;
ListNode* p=pListHead;
ListNode* q=pListHead;
for(int i=0;i<k-1;i++){
if(q->next != NULL) //考虑不够k时的情况
q = q->next;
else
return NULL;
}
while(q->next != NULL){
p = p->next;
q = q->next;
}
return p;
}
};
题目描述
输入一个链表,反转链表后,输出链表的所有元素。
思路1:新建一个 stack, 根据stack 出栈,创建新链表
class Solution {
public:
ListNode* ReverseList(ListNode* pHead) {
if(pHead == NULL || pHead->next == NULL)
return pHead;
ListNode* pNew;
stack temp;
ListNode* p=pHead;
while(p->next!=NULL){
temp.push(p);
p = p->next;
}
pNew = p;
while(!temp.empty()){
p->next = temp.top();
p = p->next;
temp.pop();
}
p->next = NULL;
return pNew;
}
};
方法二:
三个指针同时滑动,第一个是新序列的头部,第二个是原序列的头,第三个是原序列头的next
A->B->C->D->E->F
(1)
PB = A
P = B
PC = C
(2)
A<- B C->D->E->F
PB = B
P = C
PA = D
(3)
A<-B<-C D->E->F
PB = C
P = D
PA = E
……
(N)
A<-B<-C<-D<-E F->NULL
PB = E
P =F
PA = NULL
结束循环
P->next = PB
PHead(A) -> next = NULL
NULL <-A<-….-
class Solution {
public:
ListNode* ReverseList(ListNode* pHead) {
if(pHead == NULL || pHead->next == NULL)
return pHead;
ListNode *pBefore = pHead, *p = pHead->next, *pAfter = p->next;
while (pAfter) {
p->next = pBefore;
pBefore = p;
p = pAfter;
pAfter = pAfter->next;
}
p->next = pBefore;
pHead->next = NULL;
return p;
}
};
题目描述
在一个排序的链表中,存在重复的结点,请删除该链表中重复的结点,重复的结点不保留,返回链表头指针。 例如,链表1->2->3->3->4->4->5 处理后为 1->2->5
思路1:递归
class Solution {
public:
ListNode* deleteDuplication(ListNode* pHead)
{
if(pHead==NULL || pHead->next==NULL)
return pHead;
ListNode* current;
if(pHead->val == pHead->next->val){
current = pHead->next->next;
while(pHead->val == current->val && current != NULL)
current = current->next;
return deleteDuplication(current);
}
else{
current = pHead->next;
pHead->next = deleteDuplication(current);
return pHead;
}
}
};
思路2:非递归
/*
struct ListNode {
int val;
struct ListNode *next;
ListNode(int x) :
val(x), next(NULL) {
}
};
*/
class Solution {
public:
ListNode* deleteDuplication(ListNode* pHead)
{
if(pHead==NULL || pHead->next==NULL)
return pHead;
ListNode* newHead = new ListNode(-1); //防止第一个就是重复的,新建一个值为-1的节点
newHead->next = pHead;
ListNode* pre = newHead;
ListNode* p = pHead;
ListNode* pNext = p->next;
while(p!=NULL && p->next!=NULL){
pNext=p->next;
if(p->val == pNext->val){
while(pNext!=NULL && pNext->val==p->val)
pNext = pNext->next;
pre->next = pNext; //如果相同,pre的下一个往后,相当于删除
p = pNext;
}
else{ //如果当前节点和下一个节点值不等,则pre向后移动一位,不被删除
pre = p;
p = p->next;
}
}
return newHead->next;
}
};
题目描述
输入两个单调递增的链表,输出两个链表合成后的链表,当然我们需要合成后的链表满足单调不减规则。
思路一:递归
class Solution {
public:
ListNode* Merge(ListNode* pHead1, ListNode* pHead2)
{
if(!pHead1 && !pHead2)
return NULL;
// 需要一个结点记录头结点用于最后返回,另一个处于新链表的最后
if(!pHead1 || !pHead2)
return(pHead1 == NULL)? pHead2:pHead1;
ListNode* pNew;
if(pHead1->val <= pHead2->val){
pNew = pHead1;
pNew->next = Merge(pHead1->next,pHead2);
}
else{
pNew = pHead2;
pNew->next = Merge(pHead1,pHead2->next);
}
return pNew;
}
};
思路2:非递归
class Solution {
public:
ListNode* Merge(ListNode* pHead1, ListNode* pHead2)
{
if(!pHead1 && !pHead2)
return NULL;
if(!pHead1 || !pHead2)
return(pHead1 == NULL)? pHead2:pHead1;
ListNode* pNew; //头指针
if(pHead1->val<=pHead2->val){
pNew=pHead1;
pHead1=pHead1->next;
}
else{
pNew=pHead2;
pHead2=pHead2->next;
}
ListNode* p = pNew; //工作指针
while(pHead1 && pHead2){ //两个链表都有
if(pHead1->val < pHead2->val){
p->next = pHead1;
pHead1 = pHead1->next;
p = p->next;
}
else{
p->next = pHead2;
pHead2 = pHead2->next;
p = p->next;
}
}
if(pHead1 == NULL) //链表1遍历完
p->next = pHead2;
if(pHead2 == NULL) //链表2遍历完
p->next = pHead1;
return pNew;
}
};
题目描述
输入一个复杂链表(每个节点中有节点值,以及两个指针,一个指向下一个节点,另一个特殊指针指向任意一个节点),返回结果为复制后复杂链表的head。(注意,输出结果中请不要返回参数中的节点引用,否则判题程序会直接返回空)
解题思路
(1)在旧链表(例如A-B-C-D)中创建新链表(A-A’-B-B’-C-C’-D-D’),此时不处理新链表的特殊指针;
(2)根据旧链表的特殊指针,复制新链表的特殊指针;
(3)从新链表中,拆分得到复制链表。
/*
struct RandomListNode {
int label;
struct RandomListNode *next, *random;
RandomListNode(int x) :
label(x), next(NULL), random(NULL) {
}
};
*/
class Solution {
public:
RandomListNode* Clone(RandomListNode* pHead)
{
if(!pHead)
return NULL;
// 第一步,复制每一个结点,A-A'-B-B'-C-C'-D-D'
RandomListNode *currNode = pHead; //curr = A
while(currNode){
RandomListNode *node = new RandomListNode(currNode->label); //创立 A'
node->next = currNode->next; //A'->B
currNode->next = node; //A->A'
currNode = node->next; //curr = B ......循环直到NULL
}
// 第二步,复制random结点
currNode = pHead;
while(currNode){
RandomListNode *node = currNode->next;
if(currNode->random){
node->random = currNode->random->next;
}
currNode = node->next;
}
// 第三步,拆分
RandomListNode *pCloneHead = pHead->next;
RandomListNode *tmp;
currNode = pHead;
while(currNode->next){
tmp = currNode->next;
currNode->next = tmp->next;
currNode = tmp;
} //第一次循环完,A->next = B; 第二次循环完,A'->next = B';
return pCloneHead;
}
};