c++解决链表问题


链表问题主要通过双指针解决,

1. 链表中倒数第K个节点

核心:生成两个指针;指针1用于停止,一开始先一直往后遍历,遍历到第K个时,指针2开始遍历,这时候指针1和2之间的距离便是K,当指针1遍历到链表结束时,指针2停止,停止处便是原链表倒数第K个节点;

class Solution {
public:
      ListNode* FindKthToTail(ListNode* pListHead, unsigned int k) {
          ListNode* list1 = pListHead;
          ListNode* list2 = pListHead;
          int i;
          for(i=0;list1!=NULL;i++){
               if(i>=k)
                    list2 = list2->next;
               list1 = list1->next;
          }
          return (i>=k)?list2:NULL;
      }
};

2、反转链表

核心:生成两个node节点,一个用于遍历,另一个用于存储之前的遍历;具体代码参考如下

class Solution{
public:
    ListNode* ReverseList(ListNode* pHead){
        ListNode* pNode=pHead;
        ListNode* pPre=NULL;
        while(pNode!=NULL){
            ListNode* pNext=pNode->next;
            pNode->next=pPre;
            pPre=pNode;
            pNode=pNext;
        }
        return pPre;
    }
};

3、合并两个排序链表

核心:
1、生成新的链表
2、比较两个排序链表指向位置的值的大小,将小的值接在新的链表后面

class Solution {
public:
    ListNode* mergeTwoLists(ListNode* l1, ListNode* l2) {
        ListNode* head = new ListNode(0);
        ListNode* p = head;
        if (l1 == NULL) return l2;
        if (l2 == NULL) return l1;
        while (l1 && l2) {
            if (l1 -> val <= l2 -> val) {
                head -> next = l1;
                l1 = l1 -> next;
            }
            else {
                head -> next = l2;
                l2 = l2 -> next;
            }
            head = head -> next;
        }
        if (l1) {
            head -> next = l1;
        }
        else {
            head -> next = l2;
        }
        return p -> next;
    }
};

4、复杂链表的复制

核心:分为3步

  1. 复制节点
  2. 复制随机指针
  3. 拆分节点
/*
Struct RandomListNdoe{
    int label;
    struct RandomListNode *next,*random;
    RandomListNode(int) :
        label(x),next(NULL),random(BULL){
    }
};
*/

class Solution{
    RandomListNode* Clone(RandomListNode* pHead){
        if(pHead==NULL)
            return NULL;
        //复制节点
        RandomListNode* currNode=pHead;
        while(currNode){
            RandomListNode* newNode=new RandomListNode(currNode->label);
            newNode->next=currNode->next;
            currNode->next=newNode;
            currNode=newNode->next; 
        }
        //复制随机指针
        currNode=pHead;
        while(currNode){
             RandomListNode* newNode=currNode->next;
             if(currNode->random)
                 newNode->random=currNode->random->next;
             currNode=newNode->next; 
        }
        //拆分
        currNode=pHead;
        RandomListNode* pClone=currNode->next;
        while(currNode->next){
            RandomListNode* newNode=currNode->next;
            currNode->next=newNode->next;
            currNode=newNode;
        }
        return pClone;
    }
};

5、两个链表的第一个公共节点

核心:

  • 两个指针,指向两个链表的头节点
  • 当两个指针不同时,对每一个指针,判断其是否为空,为空则指向另一个链表的头节点,否则指向下一个节点
class Solution{
public:
    ListNode* FindFirstCommonNode(ListNode* pHead1,ListNode* pHead2){
        ListNode *p1=pHead1;
        ListNode *p2=Phead2;
        while(p1!=P2){
            p1=(p1==NULL?pHead2:p1->next);
            p2=(p2==NULL?pHead1:p2->next);
        }
        return p2;        
    }
};

6、链表中环的入口节点

问题:找出一个链表中环的入口节点

class Solution{
public:
    ListNode* EntryNodeOfLoop(ListNode* pHead){
        if(pHead==NULL || pHead->next==NULL)
            return NULL;
        ListNode* p1=pHead;
        ListNode* p2=pHead;
        while(p2!=NULL && p2->next!=NULL){
            p1=p1->next;
            p2=p2->next->next;
            if(p1==p2){
                p2=pHead;
                while(p1!=p2){
                    p1=p1->next;
                    p2=p2->next;
                }
                if(p1==p2)
                    return p1;
            }
        }
        return NULL;
    }
};

7、删除链表中的重复节点

问题:删除链表中的重复节点,重复节点也不保留
思路:双指针遍历

  1. 一个指针用于从前往后遍历
  2. 在指针的下一个位置处,开始另一个指针的遍历,遍历到不相等的节点后,更新
class Solution {
public:
    ListNode* deleteDuplicates(ListNode* head) {
        ListNode* p = head;
        while (p != nullptr && p->next != nullptr) {
            ListNode* t = p->next;
            while (t != nullptr && p->val == t->val) {
                t = t->next;
            }
            p->next = t;
            p = t;
        }
        return head;
    }
};
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值