链表4:合并有序链表的3道题
看了这篇文章之后,你会发现LeetCode就是在造题。
一.造题
LeetCode21 和23又是逐步拔高的题目,刷完这两道题,你会发现第1669根本不用刷。为啥呢,我们先看要求:
LeetCode21 :将两个升序链表合并为一个新的 升序 链表并返回。新链表是通过拼接给定的两个链表的所有节点组成的。
LeetCode23:合并K个升序链表。给你一个链表数组,每个链表都已经按升序排列。请你将所有链表合并到一个升序链表中,返回合并后的链表。
然后再看:
LeetCode1669题:给你两个链表 list1 和 list2 ,它们包含的元素分别为 n 个和 m 个。请你将 list1 中第 a 个节点到第 b 个节点删除,并将list2 接在被删除节点的位置。
1669题的意思就是将list1中的[a,b)区间的删掉,然后将list2接进去,你觉得难吗?如果这也是算法的话,我至少可以造出七八道题,例如:
(1)定义list1的[a,b)区间为list3,将list3和list2按照升序合并成一个链表。
(2)将list2也将区间[a,b)的元素删掉,然后将list1和list2合并成一个链表。
(3)定义list2的[a,b)区间为list4,将list2和list4合并成有序链表。
看到了吗?掌握基础是多么重要,我们自己都能造出题目来。
这也是为什么算法会越刷越少,因为到后面会发现套路就这么写,花样随便换,以不变应万变就是我们的宗旨。
二.合并两个有序链表
这种题有两种类型,一种是新建一个链表,另外一个就是这里的将一个合并到另外一个去,难度都不大,根据题目要求写就行了。
(1)基本写法
public ListNode mergeTwoLists (ListNode list1, ListNode list2) {
// write code here
ListNode newHead=new ListNode(-1);
ListNode res=newHead;
while(list1!=null||list2!=null){ //这么写,减少while的数量,可能耗时会小一些
if(list1!=null&&list2!=null){//都不为空的情况
if(list1.val<list2.val){
newHead.next=list1;
list1=list1.next;
}else if(list1.val>list2.val){
newHead.next=list2;
list2=list2.next;
}else{ //相等的情况,分别接两个链
newHead.next=list2;
list2=list2.next;
newHead=newHead.next;
newHead.next=list1;
list1=list1.next;
}
newHead=newHead.next;
}else if(list1!=null&&list2==null){
newHead.next=list1;
list1=list1.next;
newHead=newHead.next;
}else if(list1==null&&list2!=null){
newHead.next=list2;
list2=list2.next;
newHead=newHead.next;
}
}
return res.next;
}
}
(2)适合面试的写法
这个题都多种写法的,上面的都写在一个大while循环里了,看上去有点臃肿,我们可以将其拆开,第一个while只处理两个list 都不为空。之后判断list1和list2哪个不为空就接到合并后的list后面就行了,循环都不用写,也就是这样:
class Solution {
public ListNode mergeTwoLists(ListNode l1, ListNode l2) {
ListNode prehead = new ListNode(-1);
ListNode prev = prehead;
while (l1 != null && l2 != null) {
if (l1.val <= l2.val) {
prev.next = l1;
l1 = l1.next;
} else {
prev.next = l2;
l2 = l2.next;
}
prev = prev.next;
}
// 最多只有一个还未被合并完,直接接上去就行了
prev.next = l1 == null ? l2 : l1;
return prehead.next;
}
}
(3)能够给面试官下马威的写法
大部分面试官可能也只知道前面得写法,不见得一下子明白如何通过递归来做。如果面试的时候遇到了,建议先用(2)的写法写出来,面试官满意之后,接着说“我还可以用递归的方式解决这个问题”。
递归我们后面还会分析,这里先简单看一下思想。当我们将list1或者list2中拿到最小的那个结点之后,剩下的不管是list1还是list2都还是完整的链表,而且执行一样的判断逻辑,所以我们就可以通过递归的方式来继续处理:
class Solution {
public ListNode mergeTwoLists(ListNode l1, ListNode l2) {
if (l1 == null) {
return l2;
}
else if (l2 == null) {
return l1;
}
else if (l1.val < l2.val) {
l1.next = mergeTwoLists(l1.next, l2);
return l1;
}
else {
l2.next = mergeTwoLists(l1, l2.next);
return l2;
}
}
}
是不是简单得让人震惊!
三.合并K个链表
合并k个链表,有多种方式,如果面试,我倾向的方式是先将前两个合并,之后再将后面的逐步合并进来,因为这样的话,我只要将两个合并的写清楚就行了,也就是直接调用二中的方法:
class Solution {
public ListNode mergeKLists(ListNode[] lists) {
ListNode res = null;
for (ListNode list: lists) {
res = merge2Lists(res, list);
}
return res;
}
}
四.leetcode1669题
遍历找到链表1保留部分的尾节点和链表2的尾节点,将两链表连接起来。
class Solution {
public ListNode mergeInBetween(ListNode list1, int a, int b, ListNode list2) {
ListNode pre1 = list1, post1 = list1, post2 = list2;
int i = 0, j = 0;
while(pre1 != null && post1 != null && j < b){
if(i != a - 1){
pre1 = pre1.next;
i++;
}
if(j != b){
post1 = post1.next;
j++;
}
}
post1 = post1.next;
//寻找list2的尾节点
while(post2.next != null){
post2 = post2.next;
}
//链1尾接链2头,链2尾接链1后半部分的头
pre1.next = list2;
post2.next = post1;
return list1;
}
}
链表4:合并有序链表的3道题相关推荐
- 链表的建立,搜索,插入,反转,销毁以及合并有序链表。
-创建,插入,反转链表- /*关于链表的一系列操作*/ #include <stdio.h> #include <stdlib.h> typedef struct node ...
- 牛客题霸 [合并有序链表] C++题解/答案
牛客题霸 [合并有序链表] C++题解/答案 题目描述 将两个有序的链表合并为一个新链表,要求新的链表是通过拼接两个链表的节点来生成的. 题解: 首先判断l1和l2是否为空 然后依次比较l1和l2的值 ...
- SDUT_2119 数据结构实验之链表四:有序链表的归并
点击打开链接 数据结构实验之链表四:有序链表的归并 Time Limit: 1000MS Memory Limit: 65536KB Submit Statistic Discuss Problem ...
- SDUT OJ 数据结构实验之链表四:有序链表的归并
数据结构实验之链表四:有序链表的归并 Time Limit: 1000 ms Memory Limit: 65536 KiB Submit Statistic Discuss Problem Desc ...
- SDUT_2121数据结构实验之链表六:有序链表的建立 (对建立的单项链表结构进行排序)
点击打开链接 数据结构实验之链表六:有序链表的建立 Time Limit: 1000MS Memory Limit: 65536KB Submit Statistic Discuss Problem ...
- 山东理工OJ【2121】数据结构实验之链表六:有序链表的建立(插排法)
数据结构实验之链表六:有序链表的建立 Time Limit: 1000ms Memory limit: 65536K 有疑问?点这里^_^ 题目描述 输入N个无序的整数,建立一个有序链表, ...
- SDUT-2121_数据结构实验之链表六:有序链表的建立
数据结构实验之链表六:有序链表的建立 Time Limit: 1000 ms Memory Limit: 65536 KiB Problem Description 输入N个无序的整数,建立一个有序链 ...
- [PHP] 算法-合并两个有序链表为一个有序链表的PHP实现
合并两个有序的链表为一个有序的链表: 类似归并排序中合并两个数组的部分 1.遍历链表1和链表2,比较链表1和2中的元素大小 2.如果链表1结点大于链表2的结点,该结点放入第三方链表 3.链表1往下走一 ...
- 2021-10-27 PTA 数据结构 链表 两个有序链表序列的合并
题目:两个有序链表序列的合并 (本题来自PTA) 以下是AC代码(代码来源于老师所给的题解) #include<stdio.h> #include<stdlib.h> #inc ...
最新文章
- 洛谷 P2197 nim游戏
- 金融领域下的数据挖掘算法应用:XGboost模型
- 玩转GIT系列之【git的分支操作(查看分支/切换分支/新建分支/删除分支)】
- vue.jsr入门_JSR-308和Checker框架为jOOQ 3.9添加了更多类型安全性
- 零基础想学Python,明白这2点,越快年薪30W
- 字节跳动面试:java实例化对象必须调用类的构造方法
- 集宁哪有计算机培训班,集宁区有这么一个空间,叫共享自习室
- ThreadLocal原理浅析
- Python降低XGBoost 过度拟合多种方法
- snownlp 原理_情感分析snownlp包部分核心代码理解
- windows控制台cmd乱码的解决办法
- python希尔伯特变换_Hilbert变换提取信号特征的Python实现
- 阿里巴巴icon font导入CSS
- App工程结构搭建:几种常见Android代码架构分析
- 【数学建模】多元线性回归(PythonMatlab代码实现)
- Windows资源管理器占用CPU过高
- Cf252中子发射能谱模型
- 正确处理时间和时区问题(java+mysql)
- vb.NET入门总结
- 内网转发工具EW的使用