LeetCode高频算法题汇总--链表篇

题一:链表逆序a Leetcode 206

题二:链表逆序b LeetCode 92

题三: 两个链表的交点  LeetCode 160

题四:链表求环 Leetcode 141

题五 :链表划分 LeetCode 86

题六:两个排序链表合并 Leetcode 21

题七:多个排序链表合并 Leetcode 23

题八:从尾到头打印链表 剑指offer

 题九 链表倒数第K个结点 剑指offer

题十: 删除链表中重复的结点 剑指offer

 


题一:链表逆序a Leetcode 206

描述

反转一个单链表。

示例:

输入: 1->2->3->4->5->NULL
输出: 5->4->3->2->1->NULL

思路:

比较简单
遍历链表
每到一个结点逆转一个 

解法:

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode(int x) : val(x), next(NULL) {}
 * };
 */
class Solution {
public:
    ListNode* reverseList(ListNode* head) {
        if(head==NULL){return head;}
        if(head->next==NULL){return head;}
        else{
              ListNode * tmp1=NULL;
              ListNode * tmp2=head;
            while(tmp2!=NULL)
            {
                ListNode * tmp=tmp2->next;
                tmp2->next=tmp1;
                tmp1=tmp2;
                tmp2=tmp;
            }
            return tmp1;
        }
        
        
    }
};


题二:链表逆序b LeetCode 92

描述:

反转从位置 m 到 n 的链表。请使用一趟扫描完成反转。

说明:
1 ≤ m ≤ n ≤ 链表长度。

示例:

输入: 1->2->3->4->5->NULL, m = 2, n = 4
输出: 1->4->3->2->5->NULL

思路:

 找到指定位置的结点m和结点n  以及结点m-1 和结点n+1

解法 :

class Solution {
public:
    ListNode* reverseBetween(ListNode* head, int m, int n) {
        ListNode * root = new ListNode(0);  //此节点的next指向head 方便后面找到m和n的位置
        root->next = head;
        ListNode * p = root,* q = root;
        m--;
        while(m--) p = p->next; // 位置m-1处的结点p
        while(n--) q = q->next; // 位置n处的结点q
        ListNode * tail = q->next;//位置n+1处的结点tail
        ListNode * curr = p->next;//位置m处的结点curr


        //开始逆转
        ListNode * pro = tail;      
        q->next = NULL;
        while(curr)
        {
            ListNode * tmp = curr->next;
            curr->next = pro;
            pro = curr;
            curr = tmp;
        }
        p->next = pro;  
        return root->next;
    }
};

题三: 两个链表的交点  LeetCode 160

描述

思路

解法

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode(int x) : val(x), next(NULL) {}
 * };
 */
class Solution {
public:
    ListNode *getIntersectionNode(ListNode *headA, ListNode *headB) {
        int len_a =0,len_b=0;
        ListNode * tmp_a=headA,*tmp_b=headB;
        //计算两个链表长度
        while(tmp_a!=NULL){len_a++;tmp_a=tmp_a->next;}
        while(tmp_b!=NULL){len_b++;tmp_b=tmp_b->next;}


        if(len_a>=len_b){//如果a链表长度大于b链表长度

            int dis=len_a-len_b;
            ListNode *new_headA=headA;
            while(dis!=0){new_headA=new_headA->next; dis--;}//把a链表头结点移动到相应位置
           while((new_headA!=headB)&&(headB!=NULL)&&(new_headA!=NULL)){new_headA=new_headA->next;headB=headB->next;}//找到相交点
            return headB;
        }
        else//如果b链表长度大于a链表长度
        {
            int dis=len_b-len_a;
            ListNode *new_headB=headB;
            while(dis!=0){new_headB=new_headB->next; dis--;}//把b链表头结点移动到相应位置
           while((new_headB!=headA)&&(headA!=NULL)&&(new_headB!=NULL)){new_headB=new_headB->next;headA=headA->next;}//找到相交点
            return headA;
        }
        
    }
};

题四:链表求环 Leetcode 141

描述

给定一个链表,判断链表中是否有环。

为了表示给定链表中的环,我们使用整数 pos 来表示链表尾连接到链表中的位置(索引从 0 开始)。 如果 pos 是 -1,则在该链表中没有环。

示例 1:

输入:head = [3,2,0,-4], pos = 1
输出:true
解释:链表中有一个环,其尾部连接到第二个节点。


示例 2:

输入:head = [1,2], pos = 0
输出:true
解释:链表中有一个环,其尾部连接到第一个节点。

思路

用快慢指针解决
慢指针slow每次走一步
快指针fast每次走两步
这样 如果链表有环 则他们必定会在环内相遇(这是一个定理)
证明如下:


解法

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode(int x) : val(x), next(NULL) {}
 * };
 */
class Solution {
public:
    bool hasCycle(ListNode *head) {
        if(head==NULL||head->next==NULL||head->next->next==NULL){return false;}
        ListNode *slow =head;
        ListNode *fast=head->next->next;
        while(slow!=fast)
        {
            if(fast==NULL||fast->next==NULL){return false;}
            slow=slow->next;
            fast=fast->next->next;
        }
        return true;
        
    }
};

题五 :链表划分 LeetCode 86

描述:

给定一个链表和一个特定值 x,对链表进行分隔,使得所有小于 x 的节点都在大于或等于 x 的节点之前。

你应当保留两个分区中每个节点的初始相对位置。

示例:

输入: head = 1->4->3->2->5->2, x = 3
输出: 1->2->2->4->3->5


思路:

建立两个临时结点

r然后遍历该链表 
大的元素放在第一个临时结点建立的链表里面
小的元素放在第二个临时结点建立的链表里面 

题解:

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode(int x) : val(x), next(NULL) {}
 * };
 */
class Solution {
public:
    ListNode* partition(ListNode* head, int x) {
        
        ListNode* tmp_head1=new ListNode(0);
        ListNode* tmp_head2=new ListNode(0);
        ListNode* flag2=tmp_head2;
        ListNode* flag1=tmp_head1;
        ListNode*tmp=head;
        while(head){
            if(head->val>=x){tmp_head2->next=head; tmp_head2=head;}
            else{tmp_head1->next=head; tmp_head1=head;}
            head=head->next;
        }
        tmp_head1->next=flag2->next;
       tmp_head2->next=NULL;  
       return flag1->next;
        
    }
};

题六:两个排序链表合并 Leetcode 21

描述:

 

思路:

 

题解:

 


题七:多个排序链表合并 Leetcode 23

描述:

 

思路:

 

题解:

 

题八:从尾到头打印链表 剑指offer

描述:

输入一个链表,按链表从尾到头的顺序返回一个ArrayList。 

 

实现:

 题九 链表倒数第K个结点 剑指offer

 描述:


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

题解:

题十: 删除链表中重复的结点 剑指offer

 描述:

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

题解:

发布了84 篇原创文章 · 获赞 18 · 访问量 2万+

猜你喜欢

转载自blog.csdn.net/vjhghjghj/article/details/104127937