链表十大oj题

       最近学习了链表的相关知识,现在我们通过一些链表oj题对链表的一些相关知识进行巩固吧!

第一题:

        这道题该怎么玩呢?题目要求说是删除指定的节点,返回一个新的节点。那么我们可以从头遍历一遍,用一个cur作为临时变量,如果cur走到指定数的节点,就跳过该节点继续遍历直到cur为空。如果走到的不是指定数的节点,那么我们就将它拷贝到一个新的空间(用带哨兵位的头节点作为开头拷贝更为便利),需要注意的是最后一个节点的next要置成NULL,具体代码实现如下:


第二题: 

      做反转链表这道题时有两种方法:1.将每个节点按顺序依次头插到新的空间去,返回新空间的起始地址。2.利用n1、n2、n3三个变量实行迭代。现在我来讲讲第二个方法的具体实现:

 第三题:

      这道题主要考察的是快慢指针,快指针走两步慢指针走一步,题目很简单,直接上代码!

struct ListNode* middleNode(struct ListNode* head){

      struct ListNode* fast,*slow;
      fast =slow=head;
      while(fast && fast->next)
      {
          fast =fast->next->next;
          slow = slow->next;
      }
      return slow;
}

 第四题:

   这道题的解题思路和第三题非常的相似,求倒数第k个节点的方法就是用两个快慢指针,快指针先走k步,然后两个指针一起走直到快指针走到空,慢指针停留下来的地方就是倒数第k个节点。一下是此方法的实现:

struct ListNode* FindKthToTail(struct ListNode* pListHead, int k ) {
    // write code here
    struct ListNode* fast ,*slow;
    if(pListHead ==NULL)
    {
        return NULL;
    }
    fast = slow =pListHead;
    while(k--)
    {
       if(fast ==NULL)
       {
           return NULL;
       }
    
        fast =fast->next;
    }
    while(fast)
    {
        fast =fast->next;
        slow =slow ->next;
        
    }
    return slow;
    
    
}

第五题:

     这道题可以用两个指针分别遍历了l1和l2,两个指针一起走一起比较,较小的节点尾插在一个新的地方,最后返回新地方的地址,实现方式如下:

struct ListNode* mergeTwoLists(struct ListNode* list1, struct ListNode* list2){
     struct ListNode* guard =(struct ListNode*)malloc(sizeof(struct ListNode));
     struct ListNode* tail =guard;
     struct ListNode* cur1,*cur2;
     cur1 =list1;
     cur2 =list2;
     while(cur1 &&cur2)
     {
         
         if(cur1->val <cur2->val)
         {
             tail->next =cur1;
             tail =tail->next;
             cur1=cur1->next;
         }
         else
         {
             tail->next =cur2;
             tail =tail->next;

             cur2=cur2->next;
         }
     }
     while(cur1)
     {
             tail->next =cur1;
             tail =tail->next;
             cur1=cur1->next;

             
     }
     while(cur2)
     {
             tail->next =cur2;
             tail =tail->next;
             cur2=cur2->next;
             
     }
    tail->next=NULL;
    struct ListNode* tmp =guard->next;
    free(guard);
    return tmp;
}

第六题:

     这道题的难度等级是较难,但是咱们不用怕,用对正确的方法就行。我们创建两个哨兵位的头节点,第一个哨兵位的头节点尾插小于x的节点,第二个哨兵位的头节点尾插大于等于x的节点,最后将这两个链表合并成一个链表,返回guard1->next。(guard2尾插到guard1的后面),代码如下:

class Partition {
public:
    ListNode* partition(ListNode* pHead, int x) {
        // write code here
        ListNode*guard1 =(struct ListNode*)malloc(sizeof(struct ListNode));
         ListNode*guard2 =(struct ListNode*)malloc(sizeof(struct ListNode));
        
        
        ListNode*tail1,*tail2,*cur;
        tail1 =guard1;
        tail2 =guard2;
        cur =pHead;
        while(cur)
        {
            if(cur->val <x)
            {
                tail1->next =cur;
                tail1 =tail1->next;
            }
            else
            {
                tail2->next =cur;
                tail2 =tail2->next;
                
            }
            cur =cur->next;
        }
        tail1->next =guard2->next;
        free(guard2);
        ListNode*tmp =guard1->next;
        free(guard1);
        tail2->next =NULL;
        return tmp;
    }
};

第七题:

    回文就是对称,解这道题的思路就是先用之前的方法找出中间节点,再将头部到中间的节点进行逆序。最后一个指针从头,一个指针从中间节点依次比较,两个指针一直到NULL都是相等的话就是回文结构,反之就不是,实现方式如下:

class PalindromeList {
public:
    struct ListNode* middleNode(struct ListNode* head){

      struct ListNode* fast,*slow;
      fast =slow=head;
      while(fast && fast->next)
      {
          fast =fast->next->next;
          slow = slow->next;
      }
      return slow;
}
    struct ListNode* reverseList(struct ListNode* head){

   struct ListNode*n1 =NULL;
   struct ListNode*n2 =head;
   struct ListNode*n3 =NULL;
   
   while(n2)
   {
       n3 = n2->next;
       n2->next =n1;
        //实现迭代
        n1 =n2;
        n2 =n3;

   }
   return n1;
}
    bool chkPalindrome(ListNode* head) {
        // write code here
        ListNode* mid =middleNode(head);
        ListNode* rmid =reverseList(mid);
        while(head &&rmid)
        {
            if(head->val ==rmid->val)
            {
                head =head->next;
                rmid =rmid->next;
            }
            else
            {
                return false;
            }
        }
        
    return true;
    }
};

 第八题:

    这道题的思路就是先用两个指针分别遍历A和B并将节点个数求出来,如果A和B最终的头节点地址相同,那必定存在共同的节点,否则就为空。求出节点个数后求它们相减的绝对值,长节点的头指针先往后走他们节点个数的差值,再A和B同时走,最终地址相等的便是共同节点的地址。代码的具体细节与实现如下:

struct ListNode *getIntersectionNode(struct ListNode *headA, struct ListNode *headB) {
    struct ListNode *cur1,*cur2;
    cur1 =headA;
    cur2 =headB;
    int count1 =0;
    int count2 =0;
    while(cur1)
    {
        ++count1;
        cur1 =cur1->next;
    }
    while(cur2)
    {
        ++count2;
        cur2 =cur2->next;
    }
    if(cur1 != cur2)
    {
        return NULL;
    }
    int n =abs(count1-count2);
    struct ListNode* l_ong =headA;
    struct ListNode* s_hort =headB;
    if(count1 <count2)
    {
        l_ong =headB;
        s_hort =headA;
    }
    while(n--)
    {
        l_ong =l_ong->next;
    }
    while(l_ong && s_hort)
    {
        if(l_ong == s_hort)
        {
            return l_ong;
        }
        l_ong =l_ong->next;
        s_hort=s_hort->next;
    }
    return NULL;
}

第九题:

 判断是否有环我们可以用快慢指针,快指针一次走两步,慢指针一次走一步。快指针先进入环中,慢指针后进,当快指针的地址和慢指针相同时就存在环。代码如下:

bool hasCycle(struct ListNode *head) {
    struct ListNode *fast,*slow;
    slow = fast = head;
    
    
    while(fast && fast->next)
    {
        slow =slow->next;
        fast =fast->next->next;
        
        if(fast ==slow )
        {
            return true;
        }
    }
    return false;

}

第十题:

 怎样求出开始入环的第一个节点呢?在这里想为大家介绍啊一种方法:公式法

 

 那么代码就可以轻而易举写出来啦。

struct ListNode *detectCycle(struct ListNode *head) {
    struct ListNode *fast,*slow;
    fast =slow=head;
    while(fast &&fast->next)
    {
        fast = fast->next->next;
        slow = slow->next;
        if(fast ==slow)
        {
            slow =head;
            if(fast ==slow)
           {
            return fast;
           }
            while(fast &&fast->next)
           {
             fast = fast->next;
             slow = slow->next;
             if(fast ==slow)
             {
                 return fast;
             }
           }
        }
    }
    
     return NULL;
}

到这里链表oj题的讲述就结束了,如有不对就多多指正!

  • 3
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值