369. Plus One Linked List

  1.第1次while: 从前往后找到第一个不是9的位,记录。

  2.第2次while: 此位+1,后面的所有值设为0(因为后面的位都是9)。

返回时注意可能所有位数为9,需要在最前面添加一位,如果dummy.val == 1,则返回dummy位。    时间O(N), 空间O(1).

class Solution {
public ListNode plusOne(ListNode head) {
ListNode dummy = new ListNode(0);
dummy.next = head;
ListNode lastNotNine = dummy, node = head; while(node != null){
if(node.val != 9){
lastNotNine = node;
}
node = node.next;
} lastNotNine.val++;
node = lastNotNine.next;
while(node != null){
node.val = 0;
node = node.next;
}
return dummy.val == 1 ? dummy : dummy.next;
}
}

143. Reorder List

  1. findMid(head) : 找到链表的中点

  2. reverser 反转l2 链表

  3.将l1和 l2依次连接起来。

class Solution {
public void reorderList(ListNode head) {
if(head == null){
return;
}
ListNode mid = findMid(head);
ListNode l2 = mid.next;
mid.next = null;
l2 = reverse(l2);
ListNode l1 = head;
while(l1 != null && l2 != null){
ListNode next = l1.next;
l1.next = l2;
l2 = l2.next;
l1.next.next = next;
l1 = next;
}
} public ListNode findMid(ListNode head){
ListNode fast = head;
ListNode slow = head;
while(fast != null && fast.next != null){
fast = fast.next.next;
slow = slow.next;
}
return slow;
} public ListNode reverse(ListNode head){
ListNode newHead = null;
while(head != null){
ListNode next = head.next;
head.next = newHead;
newHead = head;
head = next;
}
return newHead;
}
}

142. Linked List Cycle II

因为快指针每次走2,慢指针每次走1,快指针走的距离是慢指针的两倍。而快指针又比慢指针多走了一圈。所以 head 到环的起点+环的起点到他们相遇的点的距离 与 环一圈的距离相等。

slow =  head 到环的起点+环的起点到他们相遇的点的距离。①

fast = 2 * slow。  ②

fast = slow + 一圈    ④  联立 --------------->>>>> head 到环的起点+环的起点到他们相遇的点的距离 = 一圈的距离

现在重新开始,head 运行到环起点 和 相遇点到环起点 的距离也是相等的,相当于他们同时减掉了 环的起点到他们相遇的点的距离.

public class Solution {
public ListNode detectCycle(ListNode head) {
ListNode slow = head, fast = head;
while(fast != null && fast.next != null){
slow = slow.next;
fast = fast.next.next;
if(slow == fast) break;
}
if(fast == null || fast.next == null) return null;
slow = head;
while(slow != fast){
slow = slow.next;
fast = fast.next;
}
return fast;
}
}

148. Sort List

空间复杂度不是O(1)

常见排序方法有很多,插入排序,选择排序,堆排序,快速排序,冒泡排序,归并排序,桶排序等等。。它们的时间复杂度不尽相同,而这里题目限定了时间必须为O(nlgn),符合要求只有快速排序,归并排序,堆排序,而根据单链表的特点,最适于用归并排序。为啥呢?这是由于链表自身的特点决定的,由于不能通过坐标来直接访问元素,所以快排什么的可能不太容易实现(但是被评论区的大神们打脸,还是可以实现的),堆排序的话,如果让新建结点的话,还是可以考虑的,若只能交换结点,最好还是不要用。而归并排序(又称混合排序)因其可以利用递归来交换数字,天然适合链表这种结构。归并排序的核心是一个 merge() 函数,其主要是合并两个有序链表,这个在 LeetCode 中也有单独的题目 Merge Two Sorted Lists。由于两个链表是要有序的才能比较容易 merge,那么对于一个无序的链表,如何才能拆分成有序的两个链表呢?我们从简单来想,什么时候两个链表一定都是有序的?就是当两个链表各只有一个结点的时候,一定是有序的。而归并排序的核心其实是分治法 Divide and Conquer,就是将链表从中间断开,分成两部分,左右两边再分别调用排序的递归函数 sortList(),得到各自有序的链表后,再进行 merge(),这样整体就是有序的了。因为子链表的递归函数中还是会再次拆成两半,当拆到链表只有一个结点时,无法继续拆分了,而这正好满足了前面所说的“一个结点的时候一定是有序的”,这样就可以进行 merge 了。然后再回溯回去,每次得到的都是有序的链表,然后进行 merge,直到还原整个长度。这里将链表从中间断开的方法,采用的就是快慢指针,大家可能对快慢指针找链表中的环比较熟悉,其实找链表中的中点同样好使,因为快指针每次走两步,慢指针每次走一步,当快指针到达链表末尾时,慢指针正好走到中间位置.

class Solution {
public ListNode sortList(ListNode head) {
if(head == null || head.next == null) return head;
ListNode slow = head, fast = head, pre = head;
while(fast != null && fast.next != null){
pre = slow;
slow = slow.next;
fast = fast.next.next;
}
pre.next = null;
return merge(sortList(head), sortList(slow));
} public ListNode merge(ListNode l1, ListNode l2){
if(l1 == null) return l2;
if(l2 == null) return l1;
if(l1.val < l2.val){
l1.next = merge(l1.next, l2);
return l1;
}else{
l2.next = merge(l1, l2.next);
return l2;
}
}
}

<LinkedList> 369 (高)143 (第二遍)142 148的更多相关文章

  1. 高并发第二弹:并发概念及内存模型(JMM)

    高并发第二弹:并发概念及内存模型(JMM) 感谢 : 深入Java内存模型 http://www.importnew.com/10589.html, cpu缓存一致性 https://www.cnbl ...

  2. 微信内置浏览器http请求10秒内接收不到数据会自动重发第二遍请求

    微信内置浏览器http请求10秒内接收不到数据会自动重发第二遍请求     这是个坑

  3. 深入理解计算机系统 第八章 异常控制流 Part2 第二遍

    第二遍读这本书,每周花两到三小时时间,能读多少读多少(这次看了第 508~530 页,共 23 页) 第一遍对应笔记链接 https://www.cnblogs.com/stone94/p/10206 ...

  4. 深入理解计算机系统 第八章 异常控制流 Part1 第二遍

    第二遍读这本书,每周花两到三小时时间,能读多少读多少(这次看了第 500~507 页,共 8 页) 第一遍对应笔记链接 https://www.cnblogs.com/stone94/p/101651 ...

  5. 深入理解计算机系统 第二章 信息的表示和处理 Part2 第二遍

    <深入理解计算机系统> 第三版 第二遍读这本书,每周花两到三小时时间,能读多少读多少(这次看了 29 ~ 34 页) 第一遍对应笔记链接 https://www.cnblogs.com/s ...

  6. 深入理解计算机系统 第二章 信息的表示和处理 Part1 第二遍

    <深入理解计算机系统> 第三版 第二遍读这本书,每周花两到三小时时间,能读多少读多少(这次看了 22 ~ 28 页) 第一遍对应笔记链接 https://www.cnblogs.com/s ...

  7. 深入理解计算机系统 第九章 虚拟内存 Part1 第二遍

    这次花了4小时40分钟,看了第 559~575 页,共 17 页 第一遍对应地址 https://www.cnblogs.com/stone94/p/10264044.html 注意:本章的练习题一定 ...

  8. 深入理解计算机系统 第三章 程序的机器级表示 Part2 第二遍

    第一遍对应笔记链接 https://www.cnblogs.com/stone94/p/9943779.html 本章汇编代码中常出现的几个指令及其含义 1.push 操作数的个数:1 将操作数(一般 ...

  9. 深入理解计算机系统 第三章 程序的机器级表示 Part1 第二遍

    第一遍对应笔记链接 https://www.cnblogs.com/stone94/p/9905345.html 机器级代码 计算机系统使用了多种不同形式的抽象,利用更简单的抽象模型来隐藏实现的细节. ...

随机推荐

  1. C# 二维数组 转换成 DataTable

    C# 数据转换 Overview C# 窗体操作中,有些比较特别的操作.但是为了方便我们不得不使用一些比较特别的手段. C#中二维数组转DataTable 首先,我们看一下我对二维数组的数据处理.这次 ...

  2. 报错:Something is already running on port 8000.

    在用react框架的时候,用cnpm run dev命令执行项目时,有时会出现这种错误, 这是因为你之前执行过该命令,但是没关闭,解决办法是打开任务管理器, 在进程中找到node.exe,右键关闭这个 ...

  3. 机器学习--matplotlib绘制各种图表

    机器学习三剑客:numpy.pandas.matplotlib NumPy系统是Python的一种开源的数值计算扩展.这种工具可用来存储和处理大型矩阵. pandas 是基于numpy的一种工具,该工 ...

  4. 深入理解ES6之解构

    变量赋值的痛 对象 let o = {a:23,b:34}; let a = o.a; let b = o.b; 如上文代码,我们经常会遇到在各种场合需要获取对象中的值的场景,舒服一点的是获取单个属性 ...

  5. 【VM配置】配置主机名称、网卡和yum源配置

    一,.配置主机名 为了对主机能进行分区,除了要有ip地址外还需要主机名,主机之间可以通过这个类似域名的名称来相互访问.linux系统中主机名配置文件一般在/etc/hostname文件中.另外我们也可 ...

  6. redis pipeline批量处理提高性能

    Redis使用的是客户端-服务器(CS)模型和请求/响应协议的TCP服务器.Redis客户端与Redis服务器之间使用TCP协议进行连接,一个客户端可以通过一个socket连接发起多个请求命令.每个请 ...

  7. RabbitMQ的安装与使用(Centos7,linux版本)

    1.主流的消息中间件简单介绍哦. 1).ActiveMQ是Apache出品,最流行的,能力强劲的开源消息总线,并且它一个完全支持jms(java message service)规范的消息中间件.其丰 ...

  8. Python切片中的误区与高级用法

    众所周知,我们可以通过索引值(或称下标)来查找序列类型(如字符串.列表.元组...)中的单个元素,那么,如果要获取一个索引区间的元素该怎么办呢? 切片(slice)就是一种截取索引片段的技术,借助切片 ...

  9. 01初识 JavaScript

    1.初识 JavaScript  1.1 JavaScript 是什么  l JavaScript 是世界上最流行的语言之一,是一种运行在客户端的脚本语言 (Script 是脚本的意思) l 脚本语言 ...

  10. Linux(ubuntu)下创建用户没有创建家目录

    添加-m参数即可: sudo useradd -m username #参数-m 自动创建用户的家目录 得解也.本来是会自动创建的,但是如果使用ll命令查看没有被创建的话,则应该使用此命令来创建新用户 ...