算法学习记录十二(C++)--->链表题目集合

来源:互联网 发布:课程录播软件 编辑:程序博客网 时间:2024/05/22 00:08

题目一

输入一个链表,输出该链表中倒数第k个结点。

分析

最普通的方法就是,先统计单链表中节点的个数,然后再找到n-k个节点,时间复杂度为O(n)另一个思路就是双指针,,先让前面的指针走向正想第k个节点,这样前后两个节点的差距就是k-1,之后前面两个指针一起走,前面的指针走到最后一个节点的时候,后走的那个指针就是倒数第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) {        if(k==0 || pListHead == NULL){ // 这里k的计数是从1开始的,若k为0或链表为空返回NULL              return NULL;        }        ListNode *pHead = pListHead;        ListNode *pBehind = pListHead;        while(k>1 && pHead != NULL){ // 前面的指针先走到正向第k个结点              pHead = pHead->next;            k--;        }        if(k>1||pHead==NULL){ // 结点个数小于k,返回NULL              return NULL;        }        while(pHead->next!=NULL){// 前后两个指针一起向前走,直到前面的指针指向最后一个结点             pHead=pHead->next;            pBehind=pBehind->next;        }        return pBehind; // 后面那个指针所指节点就是倒数第k个    }};

题目二

输入一个链表,反转链表后,输出链表的所有元素

分析

1.非递归 三指针 pPrev -> pNode -> pNext; 我们先保存原来的下一个指针位置,要不然翻转后其next会指向pPrev,从而丢失指向pNext的指针 接着反转指针, 然后下面指针同步后移,以便处理后面的指针2.递归核心代码,当前节点的两次next取值指向自己,就是翻转pHead->next->next=pHead;pHead->next=NULL;

代码 非递归

/*struct ListNode {    int val;    struct ListNode *next;    ListNode(int x) :            val(x), next(NULL) {    }};*//*next = head.next;//首先记录当前节点的下一个节点,(保存起来)head.next = pre;//让当前节点指向前一个节点,因为要反序嘛pre = head;//让前一个节点值,取代当前的节点值。因为要继续向下走head = next;//让下一个节点,取代当前节点。同样是向下走,为下一次循环做准备*//*class Solution {public:    ListNode* ReverseList(ListNode* pHead) {        ListNode *pNode = pHead;        ListNode *pPre = NULL;        ListNode *pNext = NULL;        while(pNode != NULL){            pNext = pNode->next;            pNode->next = pPre;            pPre = pNode;            pNode = pNext;        }        return pPre;    }};*/

代码 递归

class Solution {public:    // 这个递归非常赞 举个例子    // 例如 1->2->3-NULL  这个链表    // 当pHead为1的时候传进去  内部会调用ReverseList(2)继续传递,而且每次调用都会触发一下两行代码    // pHead->next->next=pHead;pHead->next=NULL;    // 当你调用ReverseList(3)的时候就直接返回3这个节点,不调用那两行代码,然后进行回归    // pHead->next->next=pHead; 这句话的意思是,例如节点2调用的时候,pHead是2,递归最后一层ReverseList(3)返回3    // 然后->next就是对应的3节点,再next就是反序替换节点  两个next指向当前节点,就是反转一次了    // pHead->next=NULL;这句话的意思就是最后一个节点的next为Null结束    ListNode* ReverseList(ListNode* pHead) {        //如果链表为空或者链表中只有一个元素        if(pHead==NULL||pHead->next==NULL) return pHead;        //先反转后面的链表,走到链表的末端结点        ListNode* pReverseNode=ReverseList(pHead->next);        //再将当前节点设置为后面节点的后续节点        pHead->next->next=pHead;        pHead->next=NULL;        return pReverseNode;    }};

题目三

已知两个单链表pHead1 和pHead2 各自有序,把它们合并成一个链表依然有序

分析

这个类似归并排序。尤其注意两个链表都为空,和其中一个为空时的情况。只需要O(1)的空间。时间复杂度为O(max(len1, len2))。分别用递归和常规指针进行操作

常规操作

/*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 *orginalHeader = NULL;        ListNode *currentNode = NULL;        while(pHead1 && pHead2){            if(pHead1->val < pHead2->val){                if(orginalHeader == NULL){ // 该判断为了找出对应的头结点保存到orginalHeader                    orginalHeader = currentNode = pHead1;                }                else{                    currentNode->next = pHead1; // 取下链表的当前节点放到临时链表的next节点                    currentNode = currentNode->next; // 临时节点往后移动一位                }                pHead1 = pHead1->next; // 每次比较之后都要把比较小的链表往后移动一个            }            else{                if(orginalHeader == NULL){                    orginalHeader = currentNode = pHead2;                }                else{                    currentNode->next = pHead2;                    currentNode = currentNode->next;                }                pHead2 = pHead2->next;            }        }        // 一个为空的时候结束遍历而且直接拼接到后面        if(pHead1 == NULL){            currentNode->next = pHead2;        }        else{            currentNode->next = pHead1;        }        return orginalHeader;    }};*/

递归拼接

class Solution {public:    ListNode* Merge(ListNode* pHead1, ListNode* pHead2)    {        if(pHead1 == NULL){            return pHead2;        }        if(pHead2 == NULL){            return pHead1;        }        ListNode *tempNode = NULL;        if(pHead1->val < pHead2->val){            pHead1->next = Merge(pHead1->next,pHead2);            return pHead1; // 一开始的头结点大小决定返回head1还是head2        }else{            pHead2->next = Merge(pHead1,pHead2->next);            return pHead2;        }    }};