IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 数据结构与算法 -> [数据结构与算法] 数组与链表 -> 正文阅读

[数据结构与算法][数据结构与算法] 数组与链表

[小点整合]

1、题目分析

????????(1)明确题意,包括输入输出、数据范围、考察具体的知识点;

? ? ? ? (2)列出所有的解决方法;

? ? ? ? (3)评估每种方法的时间、空间复杂度;

? ? ? ? (4)实现最优的解决方案,注意代码准确度并进行相关的测试;

? ? ? ? (5)进行复盘与整理,补充不足。

2、数组:内存中连续一段的存储区域,下标从0开始,插入与删除的平均时间复杂度为O(n),查询可以在O(1)时间完成,根据元素的下标进行访问;

? ? ? ? 链表:存储空间不连续,可以减少插入和删除操作的耗时,可以在O(1)时间内完成,但前提是花费O(n)的时间去查找该元素的位置,同时其大小不确定;形式多样。

????????两者属于“博弈、动态平衡的关系”,都有其适用的场景。


[链表相关题目]

1、反转链表

给单链表的头节点?head?,请反转链表,并返回反转后的链表。

示例 1:

输入:head = [1,2,3,4,5]
输出:[5,4,3,2,1]

示例 2:

输入:head = [1,2]
输出:[2,1]

示例 3:

输入:head = []
输出:[]

提示:

  • 链表中节点的数目范围是?[0, 5000]
  • -5000 <= Node.val <= 5000

?(1)利用外部空间:先申请一个动态扩容的数组或者容器(e.g. ArrayList);遍历链表,将链表中的元素添加到容器中;再使用容器的反转操作、或反向遍历重新存储,即可得到结果。

Collections.reverse(arrayList);

?(2)双指针迭代:可以申请两个指针,第一个指针叫 prev,最初指向 null ;第二个指针 curr 指向 head,然后不断遍历 curr。——

????????每次迭代到 curr,都将 curr 的 next 指向 prev,然后 prev 和 curr 前进一位。

????????都迭代完(curr 变成 null ),prev 就是最后一个节点了。

? ? ? ? 其中,申请一个temp变量,这个temp变量会将curr的下一个节点保存起来。

????????????????时间复杂度:O(n),假设?n 是列表的长度,时间复杂度是?O(n)。

????????????????空间复杂度:O(1)。

(3)递归解法:其关键在于反向工作。假设列表的其余部分已经被反转,现在应该如何反转它前面的部分?

????????假设列表为:

\large {\color{Blue} n_{1}\rightarrow \ldots \rightarrow n_{k-1} \rightarrow n_{k} \rightarrow n_{k+1} \rightarrow \ldots \rightarrow n_{m} \rightarrow \varnothing}

?????????若从节点?n_{k+1}到?n_m??已经被反转,而head正处于n_{k}?,如下:

???????????????????????????????? \large {\color{Blue} n_{1}\rightarrow \ldots \rightarrow n_{k-1} \rightarrow n_{k} \rightarrow n_{k+1} \leftarrow \ldots \leftarrow n_{m}}

????????希望?n_{k+1}?的下一个节点指向?n_{k},

????????所以,\large {\color{Red} n_k.\textit{next}.\textit{next} = n_{k}}?。

????????要小心的是 \large n_{1}的下一个必须指向 \varnothing。如果忽略了这一点,链表中可能会产生循环。如果使用大小为 2 的链表测试代码,则可能会捕获此错误。

????????????????时间复杂度:O(n),假设 n 是列表的长度,时间复杂度为 O(n)。
????????????????空间复杂度:O(n),使用递归,将会使用隐式栈空间,深度可能会达到 n 层。

reverseList: head=1
    reverseList: head=2
	    reverseList: head=3
		    reverseList:head=4
			    reverseList:head=5 
					终止返回
				cur = 5
				4.next.next->4,即5->4
			cur=5
			3.next.next->3,即4->3
		cur = 5
		2.next.next->2,即3->2
	cur = 5
	1.next.next->1,即2->1
	
	最后返回cur
/**
 * Definition for singly-linked list.
 * public class ListNode {
 *     int val;
 *     ListNode next;
 *     ListNode() {}
 *     ListNode(int val) { this.val = val; }
 *     ListNode(int val, ListNode next) { this.val = val; this.next = next; }
 * }
 */
// 迭代求解:双指针
class Solution {
    public ListNode reverseList(ListNode head) {
        // 首先判断链表是否为空
        if(head == null){
            return null;
        }

        // 声明存储空间,双指针法
        ListNode curr = head;
        ListNode prev = null;
        while(curr != null){
            ListNode temp = curr.next;
            curr.next = prev;
            prev = curr;
            curr = temp;
        }

        return prev;
    }
}
/**
 * Definition for singly-linked list.
 * public class ListNode {
 *     int val;
 *     ListNode next;
 *     ListNode() {}
 *     ListNode(int val) { this.val = val; }
 *     ListNode(int val, ListNode next) { this.val = val; this.next = next; }
 * }
 */
class Solution {
    public ListNode reverseList(ListNode head) {
        // 判断递归的结束条件
        if(head == null || head.next == null){
            return head;
        }
        
        // 递归求解
        ListNode curr = reverseList(head.next);
        // 调整方向并删除原始指向关系
        head.next.next = head;
        head.next = null;

        return curr;
    }
}

?2、反转链表二:指针的指向修改

????????给单链表的头指针?head?和两个整数?left?和?right?,其中?left <= right?。请反转从位置?left?到位置?right?的链表节点,返回?反转后的链表?。

示例 1:

输入:head = [1,2,3,4,5], left = 2, right = 4
输出:[1,4,3,2,5]

示例 2:

输入:head = [5], left = 1, right = 1
输出:[5]

提示:

  • 链表中节点数目为?n
  • 1 <= n <= 500
  • -500 <= Node.val <= 500
  • 1 <= left <= right <= n

(1)双指针头插法:

? ? ? ? a、定义两个指针,分别称之为 g(guard 守卫) 和 p(point):首先根据方法的参数 m 确定 g 和 p 的位置。将 g 移动到第一个要反转的节点的前面,将 p 移动到第一个要反转的节点的位置上。以 m=2,n=4为例。
? ? ? ? b、将 p 后面的元素删除,然后添加到 g 的后面。即头插法。
????????c、根据 m 和 n 重复步骤(b)
????????d、返回 dummyHead.next

https://leetcode-cn.com/problems/reverse-linked-list-ii/solution/java-shuang-zhi-zhen-tou-cha-fa-by-mu-yi-cheng-zho/

img1.png?

img2.png

/**
 * Definition for singly-linked list.
 * public class ListNode {
 *     int val;
 *     ListNode next;
 *     ListNode() {}
 *     ListNode(int val) { this.val = val; }
 *     ListNode(int val, ListNode next) { this.val = val; this.next = next; }
 * }
 */
class Solution {
    public ListNode reverseBetween(ListNode head, int left, int right) {

        // 判断链表是否为空
        if(head == null){
            return new ListNode(0);
        }

        // 计算链表的长度,遍历(从头到尾打印链表,面试题06)
        int linkedlistLen = 0;
        ListNode temp = head;
        while(temp != null){
            linkedlistLen += 1;
            temp = temp.next;
        }

        // 判定left 、 right的大小关系(扩充情况)
        // 1、left right长度均在链表内但right < left
        // 2、在left <= right条件下,left在链表内但right超出界限
        // 3、在left <= right条件下,left已经超出链表长度
        // 4、left right长度均在链表内,且left <= right
        if(left < linkedlistLen && right < linkedlistLen && left > right){
            int flag = left;
            left = right;
            right = flag;
        }else if(left <= right && left < linkedlistLen && right > linkedlistLen){
            right = linkedlistLen;
        }else if(left <= right && left > linkedlistLen){
            return head;
        }else if(left <= right && left < linkedlistLen && right < linkedlistLen){
            // 进行后续操作,左右边界不变
        }

        // 使用头插法进行反转
        // 创建哑节点,dummyHead
        ListNode dummyHead = new ListNode(0);
        dummyHead.next = head;

        // 初始化双指针
        ListNode guard = dummyHead;
        ListNode point = dummyHead.next;
        // 移动指针到相应的left位置
        for(int i = 0; i < left - 1; i ++){
            guard = guard.next;
            point = point.next;
        }

        // 头插法插入节点
        for(int i = 0; i < right - left; i ++){
            ListNode target = point.next;
            point.next = point.next.next;

            target.next = guard.next;
            guard.next = target; 
        }

        // 返回头节点
        return dummyHead.next;

    }
}

  数据结构与算法 最新文章
【力扣106】 从中序与后续遍历序列构造二叉
leetcode 322 零钱兑换
哈希的应用:海量数据处理
动态规划|最短Hamilton路径
华为机试_HJ41 称砝码【中等】【menset】【
【C与数据结构】——寒假提高每日练习Day1
基础算法——堆排序
2023王道数据结构线性表--单链表课后习题部
LeetCode 之 反转链表的一部分
【题解】lintcode必刷50题<有效的括号序列
上一篇文章      下一篇文章      查看所有文章
加:2021-07-13 17:44:00  更:2021-07-13 17:45:25 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年5日历 -2024/5/8 16:06:04-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码