链表相关的leetcode重要题目

Leetcode 92:反转链表II

解决这道题需要三个步骤:

  1. 找到需要反转的第一个节点。可以通过头节点前进m-1步,找到反转开始的位置。
  2. 将需要反转的部分进行反转。参考Leetcode 206:反转链表
  3. 将反转部分与剩余部分进行链接。其中分为两种情况,m=1与m>1。当m=1时,仅需要将反转部分反转前的头节点的next指向反转部分反转前尾节点的后继,新链表的头节点为反转部分反转前的尾节点。当m>1时,还需要将反转部分反转前头节点的前驱的next指向反转部分反转前的末节点,新链表的头节点仍为原链表的头节点。假设m=2,n=4,其中有以下几个关键节点:
class Solution {
public:
    ListNode* reverseBetween(ListNode* head, int m, int n) {
        int change_len = n - m + 1; //需要反转的长度
        ListNode *pre_head = NULL; //反转部分的前驱节点
        ListNode *result = head;
        while(head && --m) //移动到反转的开始位置
        {
            pre_head = head;
            head = head->next;
        }
        ListNode *tmp = head; //反转部分头节点,即反转后的尾节点
        ListNode *new_head = NULL;
        while(head && change_len) //反转部分链表
        {
            ListNode *next = head->next;
            head->next = new_head;
            new_head = head;
            head = next;
            change_len--;
        }
        tmp->next = head; //反转后的尾节点链接反转段的后一个节点
        if (pre_head) //前驱节点不为空,说明m>1
        {
            pre_head->next = new_head; //反转部分的前驱节点连接反转后的头节点
        }
        else
        {
            result = new_head;
        }
        return result;
    }
};

Leetcode 142:环形链表II

解决这个问题需要两个步骤:

  1. 使用快慢指针判断链表是否存在环。慢指针在链表中一次走一步,快指针一次走两步,如果链表中存在环,快慢指针总会到达同一个节点meet。
  2. 从链表的头节点head以及meet同时出发,两个指针速度相同,相遇时即为环的起点。

    设绿色部分为a,蓝色部分为b,黄色部分为c。可知快指针走过的路程时慢指针的两倍,即2(a+b)=a+b+c+b,可以得到a=c,所以head节点与meet节点相遇时即为环的起点。

    class Solution {
    public:
     ListNode *detectCycle(ListNode *head) {
         ListNode* fast = head;
         ListNode* slow = head;
         ListNode* meet = NULL;
         while(fast)
         {
             fast = fast->next;
             slow = slow->next;
             if(!fast)
                 return NULL;
             else
                 fast = fast->next;
             if(fast == slow)
             {
                 meet = fast;
                 break;
             }
         }
         if (meet == NULL)
             return NULL;
         while(head && meet)
         {
             if(head == meet)
                 return meet;
             head = head->next;
             meet = meet->next;
         }
         return NULL;
     }
    };

    Leetcode 138:复制带随机指针的链表

解决这个问题需要三个步骤:

  1. 复制节点,将复制的节点连接到原节点之后,原节点的next连接到复制的节点之后。
  2. 复制随机指针。
  3. 分离节点。
class Solution {
public:
    Node* copyRandomList(Node* head)
    {
        if (!head) return nullptr;
        Node* curnode = head;
        while (curnode) //遍历原链表复制节点
        {
            Node* copy = new Node(curnode->val, curnode->next, nullptr);
            Node* tmp = curnode->next;
            curnode->next = copy;
            curnode = tmp;
        }
        curnode = head;
        while (curnode) //遍历链表连接复制节点的随机指针
        {
            if (curnode->random)
                curnode->next->random = curnode->random->next;
            curnode = curnode->next->next;
        }
        curnode = head;
        Node* new_head = head->next; //复制节点的头节点
        while (curnode->next) //分离节点
        {
            Node* tmp = curnode->next;
            curnode->next = curnode->next->next;
            curnode = tmp;
        }
        return new_head;
    }
}; 

Leetcode 23:合并K个排序链表

解决此题的思路类似于归并排序,对于两个排序列表的合并可以参考Leetcode 21:合并两个有序链表,在对k个排序链表进行合并时,可以通过分治的思想,对k个链表两两进行合并。

class Solution {
public:
    ListNode* mergeKLists(vector<ListNode*>& lists) {
        if(lists.size() == 0)
            return NULL;
        if(lists.size() == 1)
            return lists[0];
        if(lists.size() == 2)
            return mergeTwoLists(lists[0],lists[1]);
        int size = lists.size();
        int mid = size/2;
        vector<ListNode*> tmp1;
        vector<ListNode*> tmp2;
        for(int i = 0;i < mid;i++)
        {
            tmp1.push_back(lists[i]);
        }
        for(int i = mid;i < size;i++)
        {
            tmp2.push_back(lists[i]);
        }
        ListNode* l1 = mergeKLists(tmp1);
        ListNode* l2 = mergeKLists(tmp2);
        return mergeTwoLists(l1,l2);
    }

    ListNode* mergeTwoLists(ListNode* list1,ListNode* list2) //合并两个有序链表
    {
        ListNode new_head(0);
        ListNode* prenode = &new_head;
        while(list1&&list2)
        {
            if(list1->val>list2->val)
            {
                prenode->next=list2;
                list2 = list2->next;
            }
            else
            {
                prenode->next = list1;
                list1 = list1->next;
            }
            prenode = prenode->next;
        } 

        if(list1) //如果list1不为空,将剩余节点连接在已合并的链表之后
            prenode->next = list1;
        if(list2) //list2同理
            prenode->next = list2;
        return new_head.next;
    }
};

原文地址:https://www.cnblogs.com/gcheeze/p/11006968.html

时间: 2024-11-08 20:51:08

链表相关的leetcode重要题目的相关文章

剑指offer题目系列三(链表相关题目)

本篇延续上一篇剑指offer题目系列二,介绍<剑指offer>第二版中的四个题目:O(1)时间内删除链表结点.链表中倒数第k个结点.反转链表.合并两个排序的链表.同样,这些题目并非严格按照书中的顺序展示的,而是按自己学习的顺序,每个题目包含了分析和代码. 9.O(1)时间内删除链表结点 题目: 在O(1)时间内删除链表结点.给定单链表的头指针和一个结点指针,定义一个方法在O(1)时间内删除该结点. 单链表的定义如下: 解答: 单向链表删除一个结点,最直观的想法是从链表的头结点开始顺序遍历查找要

【常用算法思路分析系列】链表相关高频题集

本文是[常用算法思路分析系列]的第四篇,总结链表相关的高频题目和解题思路.本文分析如下几个问题:1.环形链表的差值问题:2.只能访问单个结点的删除问题:3.链表的分化:4.打印两个链表的公共部分:5.把链表的每k个结点逆序:6.删除链表中指定结点:7.判断链表是否为回文结构:8.复杂链表的复制:9.判断链表是否有环:10.判断两个无环链表是否相交:11.判断两个有环链表是否相交:12.判断两个链表(状态未定)是否相交. 本系列前三篇导航: [常用算法思路分析系列]排序高频题集 [常用算法思路分析

LeetCode SQL题目(第一弹)

LeetCode SQL题目 注意:Leetcode上的SQL编程题都提供了数据表的架构程序,只需要将它贴入本地数据库即可调试自己编写的程序 不管是MS-SQL Server还是MySQL都需要登陆才能使用,我没有使用SSMS 或Workbench,而是直接使用sqlcmd,解决登陆问题可以参考这个链接(http://www.cnblogs.com/skynothing/archive/2010/08/26/1809125.html)感谢这位博主的帮助. 181. Employees Earni

leetcode 单链表相关题目汇总

  leetcode-19-Remove Nth From End of List—移除链表中倒数第n个元素 leetcode-21-Merge Two Sorted Lists—两个已排序链表归并 leetcode-23-Merge k Sorted Lists—k个已排序链表归并 leetcode-24-Swap Nodes in Pairs—链表中元素两两一组交换 leetcode-25-Reverse Nodes in K-Group—链表中元素k个一组逆序 leetcode-61-Ro

链表相关题目-leetcode简单

目录 1. 合并两个有序链表 2. 删除排序链表中的重复元素 3. 环形链表 4.相交链表 5.移除链表元素 6.反转链表 7.回文链表 8.删除链表中的节点 9.链表的中间节点 1. 合并两个有序链表 将两个有序链表合并为一个新的有序链表并返回.新链表是通过拼接给定的两个链表的所有节点组成的. 方法一.利用递归思想 class Solution { public: ListNode* mergeTwoLists(ListNode* l1, ListNode* l2) { if(l1==null

链表相关题目总结

一.两数相加: 由于是刷的第一题,先写下: 本题是两个链表相加,方法是生成一个新的链表(其实是一个节点不断指向下一个节点,这样依次连起来的)去存储这个两个的和. 首先生成一个新的链表h,h是头指针:然后再让指针t指向h.    新建私有方法,该方法的作用是返回链表的有效数据,并让链表指向后继节点.即p好p->next指向相同的地址. 然后建立一个进位标志carry,让sum = x + y  + carry:,将sum %10作为新节点node的初始值.让node和*t指向相同的地址,记住*t是

链表相关算法题总结 1

链表题目对算法的要求度不高,但实际写的过程中需要注意语言细节,考虑精细度的地方很多. 1.链表结构与基本操作 1.1 添加节点 一般情况: cur ->next = prev ->next; prev ->next = cur; 表头插入: cur ->next = head; head = cur; 1.2删除节点 一般情况:(已知待删除节点的前驱节点) ListNode* temp = prev->next; prev->next = prev->next-&

LeetCode Animation 题目图解汇总(持续更新中...)

我会尽力将LeetCode上所有的题目都用动画的形式演示出来,期待与你见证这一天! GitHub Repo:LeetCode Animation Follow: MisterBooo · GitHub Problems ID Problem Article Animation 001 两数之和 每天一算:Two Sum 019 删除链表的倒数第N个节点 每天一算:Remove Nth Node From End of List 020 有效的括号 每天一算:Valid Parentheses 0

LeetCode 十月份题目汇总

开源地址:点击该链接 前言 十月份共有60道题目,全部属于 Easy 难度的,所以公众号中分享出来的并不多,只是挑了一些感觉还可以的才分享了出来,这60道题目我按照不同类别进行了分类整理,所有源码以及对应的解题思路均匀开源到 GitHub,公众号内回复"LeetCode"获取,具体题目如下. 题目分类 数组 0001_two_sum 0026_remove_duplicates_from_sorted_array 0027_remove_element 0035_search_inse