剑指offer 链表系列题目

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/u014303647/article/details/82025518

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;
}

猜你喜欢

转载自blog.csdn.net/u014303647/article/details/82025518
今日推荐