• 牛客网剑指offer链表题目总结(共8道)


    牛客网剑指offer链表题目总结(共8道)

    1、从尾到头打印链表(剑指3)

    输入一个链表,按链表从尾到头的顺序返回一个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> ans;
            if(head==NULL) return ans;
            stack<ListNode*> s;
            while(head!=NULL){
                s.push(head);
                head=head->next;
            }
            while(!s.empty()){
                ans.push_back(s.top()->val);
                s.pop();
            }
            return ans;
        }
    };
    

    方法二:递归

    /**
    *  struct ListNode {
    *        int val;
    *        struct ListNode *next;
    *        ListNode(int x) :
    *              val(x), next(NULL) {
    *        }
    *  };
    */
    class Solution {
    public:
        vector<int> ans;
        vector<int> printListFromTailToHead(ListNode* head) {
            ListNode *p=head;
            if(p!=NULL){
                if(p->next!=NULL){
                    printListFromTailToHead(p->next);
                }
                ans.push_back(p->val);
            }
            return ans;
        }
    };
    

    2、链表中倒数第k个结点(剑指14)

    快慢指针

    /*
    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||k==0) return NULL; 
            ListNode *quick=pListHead;
            ListNode *slow=pListHead;
            ListNode *head=pListHead;
            int len=1;
            while(head->next!=NULL){
                head=head->next;
                len++;
            }
            if(k>len) return NULL;
            for(int i=1;i<k;i++)
            {
                if(quick->next!=NULL)
                    quick=quick->next;
            }
            while(quick->next!=NULL){
                quick=quick->next;
                slow=slow->next;
            }
            return slow;
        }
    };
    

    3、反转链表(剑指15,同leetcode206)

    /*
    struct ListNode {
    	int val;
    	struct ListNode *next;
    	ListNode(int x) :
    			val(x), next(NULL) {
    	}
    };*/
    class Solution {
    public:
        ListNode* ReverseList(ListNode* pHead) {
            if(pHead==NULL||pHead->next==NULL) return pHead;
            ListNode *head=ReverseList(pHead->next);
            pHead->next->next=pHead;
            pHead->next=NULL;
            return head;
        }
    };
    

    4、合并两个排序的链表(剑指16,同leetcode21)

    输入两个单调递增的链表,输出两个链表合成后的链表,当然我们需要合成后的链表满足单调不减规则。

    /*
    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;
            if(pHead1->val<pHead2->val){
                pHead1->next=Merge(pHead1->next,pHead2);
                return pHead1;
            } 
            else{
                pHead2->next=Merge(pHead1,pHead2->next);
                return pHead2;
            } 
        }
    };
    

    5、复杂链表的复制(剑指25)

    输入一个复杂链表(每个节点中有节点值,以及两个指针,一个指向下一个节点,另一个特殊指针random指向一个随机节点),请对此链表进行深拷贝,并返回拷贝后的头结点。(注意,输出结果中请不要返回参数中的节点引用,否则判题程序会直接返回空)

    /*
    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==NULL) return pHead;
            RandomListNode* curNode=pHead;
    
            //复制每个节点,如:复制节点A得到A1,将A1插入节点A后面
            while(curNode!=NULL){
                RandomListNode* cloneNode=new RandomListNode(curNode->label);
                RandomListNode* nextNode=curNode->next;
                curNode->next=cloneNode;
                cloneNode->next=nextNode;
                curNode=nextNode;
            }
            //遍历链表,A1->random = A->random->next;
            curNode=pHead;
            while(curNode!=NULL){
                curNode->next->random=curNode->random==NULL?NULL:curNode->random->next;
                curNode=curNode->next->next;
            }
            //将链表拆分成原链表和复制后的链表
            curNode=pHead;
            RandomListNode* Head=pHead->next;
            while(curNode!=NULL){
                RandomListNode* cloneNode=curNode->next;
                curNode->next=cloneNode->next;
                cloneNode->next=cloneNode->next==NULL?NULL:cloneNode->next->next;
                curNode=curNode->next;
            }
            return Head;
        }
    };
    

    6、两个链表的第一个公共结点(剑指36,同leetcode160)

    输入两个链表,找出它们的第一个公共结点。(注意因为传入数据是链表,所以错误测试数据的提示是用其他方式显示的,保证传入数据是正确的)

    /*
    struct ListNode {
    	int val;
    	struct ListNode *next;
    	ListNode(int x) :
    			val(x), next(NULL) {
    	}
    };*/
    class Solution {
    public:
        ListNode* FindFirstCommonNode( ListNode* pHead1, ListNode* pHead2) {
            int len1=getLen(pHead1);
            int len2=getLen(pHead2);
            if(len1>len2) pHead1=goSteps(pHead1,len1-len2);
            else pHead2=goSteps(pHead2,len2-len1);
            while(pHead1!=NULL&&pHead2!=NULL){
                if(pHead1->val==pHead2->val) return pHead1;
                pHead1=pHead1->next;
                pHead2=pHead2->next;
            }
            return pHead1;
        }
        ListNode * goSteps(ListNode *node,int k){
            if(node==NULL||k<=0) return node;
            while(k--){
                node=node->next;
            }
            return node;
        }
        int getLen(ListNode * node){
            if(node==NULL) return 0;
            int len=1;
            while(node->next!=NULL){
                node=node->next;
                len++;
            }
            return len;
        }
    };
    

    7、链表中环的入口结点(剑指55,同leetcode142)

    /*
    struct ListNode {
        int val;
        struct ListNode *next;
        ListNode(int x) :
            val(x), next(NULL) {
        }
    };
    */
    class Solution {
    public:
        ListNode* EntryNodeOfLoop(ListNode* pHead)
        {
            ListNode* quick=pHead;
            ListNode* slow=pHead;
            while(quick!=NULL&&quick->next!=NULL){
                quick=quick->next->next;
                slow=slow->next;
                if(quick==slow) break;
            }
            if(quick==NULL||quick->next==NULL) return NULL;
            ListNode* node=pHead;
            while(node!=quick){
                node=node->next;
                quick=quick->next;
            }
            return node;
        }
    };
    

    8、删除链表中重复的结点(剑指56)

    在一个排序的链表中,存在重复的结点,请删除该链表中重复的结点,重复的结点不保留,返回链表头指针。 例如,链表1->2->3->3->4->4->5 处理后为 1->2->5

    /*
    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 *node=pHead->next;
            if(node->val==pHead->val){
                while(node!=NULL&&node->val==pHead->val){
                    node=node->next;
                }
                return deleteDuplication(node);
            }
            else{
                pHead->next=deleteDuplication(node);
                return pHead;
            } 
        }
    };
    
  • 相关阅读:
    小组自评、互评及反馈
    "一个程序员的生命周期"读后感
    阅读《构建之法》第10-12章
    阅读《构建之法》第8,9,10章
    冒泡算法程序分析树的评论
    1014 C语言文法定义与C程序的推导过程
    0917 实验一词法分析程序
    0909 我与编译原理不得不说的秘密
    复利计算器4
    复利及单利计算
  • 原文地址:https://www.cnblogs.com/yjcoding/p/13217030.html
Copyright © 2020-2023  润新知