Leetcode刷题顺序 1 链表专题


链表与数组

链表和数组作为算法中的两个基本数据结构,在算法设计是基础的.


数组在物理存储单元中是连续和线性的,得益于物理存储中的优势,数组在索引数据时的时间复杂度可以达到O(1),本质上为内存的偏移定向,而当要删除或添加元素时时间复杂度会达到O(n)


链表在物理存储单元中是非连续非线性的,可以很好的运用内存中的碎片空间.在删除和添加结点上时间复杂度为O(1),而当查找时时间复杂度为O(n)

1.链表逆序 LeetCode 206

反转一个单链表。

示例:

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

/**
 * Definition for singly-linked list.
 * public class ListNode {
 *     int val;
 *     ListNode next;
 *     ListNode(int x) { val = x; }
 * }
 */
class Solution {
    public ListNode reverseList(ListNode head) {
        ListNode newHead=null; //新的链表
        while(head!=null){
            ListNode newNext=head.next;//备份 newNext  2->3->4->5->NULL
            head.next=newHead;	//翻转操作 原子结点成为原父节点的父节点 head.next -> null
            newHead=head;//移位 newHead 接受不断传下来的head头节点 newHeda 1->null
            head=newNext;//不断得到迭代 把原来的链表一个个取出来 head 2->3->4->5->null
        }
        return newHead;
    }
}

内存消耗超过97%

2.链表逆序b LeetCode 92

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

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

示例:

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

/**
 * Definition for singly-linked list.
 * public class ListNode {
 *     int val;
 *     ListNode next;
 *     ListNode(int x) { val = x; }
 * }
 */
class Solution {
    public ListNode reverseBetween(ListNode head, int m, int n) {
        int change_len=n-m+1;  //要交换节点的次数
        ListNode preHead=null; 
        ListNode result=head;
        ListNode newHead=null;
        while(head!=null && --m!=0){ //将链表后移到要交换的位置
            preHead=head;
            head=head.next;
        }
        ListNode modify_tail=head; //原来的头指针

        while(change_len!=0 && head!=null ){
            ListNode newNext=head.next;  //备份head.next
            head.next=newHead;		//翻转
            newHead=head;			//继承
            head=newNext;			//迭代
            change_len--;			//记录要交换的次数
        }
        
        modify_tail.next=head;   //重新将指针指向现在的头节点
        if(preHead!=null){  //一般情况
            preHead.next=newHead;
        }else{ //处理直接从起始位置交换的情况
            result=newHead;
        }
        return result;
        

    }
}

内存消耗超过94%

3.链表求环 Leetcode 142

给定一个链表,返回链表开始入环的第一个节点。 如果链表无环,则返回 null。

为了表示给定链表中的环,我们使用整数 pos 来表示链表尾连接到链表中的位置(索引从 0 开始)。 如果 pos 是
-1,则在该链表中没有环。注意,pos 仅仅是用于标识环的情况,并不会作为参数传递到函数中。

说明:不允许修改给定的链表
示例 1:

在这里插入图片描述

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

快慢指针法
小象学院

/**
 * Definition for singly-linked list.
 * class ListNode {
 *     int val;
 *     ListNode next;
 *     ListNode(int x) {
 *         val = x;
 *         next = null;
 *     }
 * }
 */
public class Solution {
    public ListNode detectCycle(ListNode head) {
        ListNode fast=head;
        ListNode slow=head;
        ListNode meet=null;
        while(fast!=null){
            fast=fast.next;
            slow=slow.next;
            if(fast!=null){ //多走一步
                fast=fast.next;
            }
            if(fast==slow){
                meet=fast; //记录meet位置
                break;
            }
        }
        if(meet==null){
            return null;
        }
        while(meet!=null && head!=null){
            if(head==meet){
                return meet;
            }
            head=head.next;    //两边同时前进相同的步数将会在 环的起始位置相遇
            meet=meet.next;
        }
        return null;
    }
}

执行用时超100%,内存消耗超95%

4.链表划分 LeetCode 138

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

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

示例:

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

/**
 * Definition for singly-linked list.
 * public class ListNode {
 *     int val;
 *     ListNode next;
 *     ListNode(int x) { val = x; }
 * }
 */
class Solution {
    public ListNode partition(ListNode head, int x) {
        ListNode lessHead=new ListNode(0); //小于的一部分
        ListNode moreHead=new ListNode(0);//大与的一部分
        ListNode lessPtr=lessHead;
        ListNode morePtr=moreHead;
        while(head!=null){
            if(head.val<x){
                lessPtr.next=head;     //小于的一个提出来放到小于部分里的
                lessPtr=lessPtr.next;
            }else{
                morePtr.next=head;	  //大于的一个提出来放到大于部分里的
                morePtr=morePtr.next;
            }
            head=head.next;   //判别下一个
        }
        lessPtr.next=moreHead.next;  //合并两个部分
        morePtr.next=null;		//置空
        return lessHead.next;
    }
}

内存消耗超95%

链表深度拷贝 LeetCode 138

给定一个链表,每个节点包含一个额外增加的随机指针,该指针可以指向链表中的任何节点或空节点。

要求返回这个链表的 深拷贝。

我们用一个由 n 个节点组成的链表来表示输入/输出中的链表。每个节点用一个 [val, random_index] 表示:

val:一个表示 Node.val 的整数。 random_index:随机指针指向的节点索引(范围从 0 到
n-1);如果不指向任何节点,则为 null

示例1

在这里插入图片描述

输入:head = [[7,null],[13,0],[11,4],[10,2],[1,0]]
输出:[[7,null],[13,0],[11,4],[10,2],[1,0]

/*
// Definition for a Node.
class Node {
    int val;
    Node next;
    Node random;

    public Node(int val) {
        this.val = val;
        this.next = null;
        this.random = null;
    }
}
*/

class Solution {
    public Node copyRandomList(Node head) {
        Map<Node,Integer> map1 =new HashMap<Node,Integer>();     //通过存储结点map来获取他所在的索引位置
        ArrayList<Node> vec=new ArrayList<Node>();   //遍历新的链表
        Node ptr=head;			//操作指针
        int i=0;
        while(ptr!=null){
            vec.add(new Node(ptr.val));   	//新建Node并放入链表中
            map1.put(ptr,i);			//存储在map中
            ptr=ptr.next;				//下一个操作结点
            i++;					

        }
        vec.add(null);			//边界操作,当要遍历最后一个结点时仍然适用
        ptr=head;
        i=0;
        while(ptr!=null){
            vec.get(i).next=vec.get(i+1);	//结点的链接
            if(ptr.random!=null){			//若随机指引结点不为空执行链接
                int id =map1.get(ptr.random); //获取随机链表的索引id
                vec.get(i).random=vec.get(id); //指引结点
            }
            i++;
            ptr=ptr.next; //下一个操作结点
        }

        return vec.get(0);
    }
}

总结

以上是LeetCode中经典链表题的解答

致谢:小象学院leetcode刷题教程

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
根据引用\[1\]和引用\[2\]的内容,推荐的LeetCode刷题顺序是按照题目类型刷题,优先选择树、链表、二分查找、DFS、BFS、动态规划等常见类型的题目。可以先做2~4道简单题,然后再做中等难度的题目。在选择题目时,可以优先选择题目序号小、点赞多、提交成功率高的题目,这样可以从简单入手,节省时间。同时,LeetCode每道题目都有“模拟面试”功能,可以给自己设定时间限制,如果做不出来可以看答案,然后记住思路后再自己尝试一遍。每种类型的题目做完10+道后,可以总结规律。 根据引用\[3\]的内容,题目可以按照不同的分类进行刷题,比如数组与贪心算法、子数组与贪心算法、子序列与贪心算法、数字与贪心、单调栈法、双指针法等。可以根据自己的兴趣和需求选择相应的题目进行刷题。 综上所述,LeetCode刷题顺序可以按照题目类型或者题目分类进行选择。 #### 引用[.reference_title] - *1* [LeetCode 刷题顺序,按标签分类,科学刷题!](https://blog.csdn.net/fengyuyeguirenenen/article/details/125099023)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^koosearch_v1,239^v3^insert_chatgpt"}} ] [.reference_item] - *2* [leetcode 刷题指南 & 刷题顺序](https://blog.csdn.net/qijingpei/article/details/125561071)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^koosearch_v1,239^v3^insert_chatgpt"}} ] [.reference_item] - *3* [leetcode-刷题顺序推荐](https://blog.csdn.net/weixin_38087674/article/details/114107841)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^koosearch_v1,239^v3^insert_chatgpt"}} ] [.reference_item] [ .reference_list ]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

花葉言

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值