网站首页 > 文章精选 正文
面试大厂,算法基本是必面的,特别是字节跳动,技术面最后一个问题就是算法题,这次给大家带来一道字节跳动面试出的一道简单算法题。
请听题:
输入两个递增排序的链表,合并这两个链表并使新链表中的节点仍然是递增排序的。并返回合并后的链表表头。
难度:简单
示例1:
输入:1->2->4, 1->3->4
输出:1->1->2->3->4->4
限制:
0 <= 链表长度 <= 1000
请完成代码编写:
/**
* Definition for singly-linked list.
* public class ListNode {
* int val;
* ListNode next;
* ListNode(int x) { val = x; }
* }
*/
class Solution {
public ListNode mergeTwoLists(ListNode head1, ListNode head2) {
//to do this
}
题目是这么个题目,看着不难,确实也不难的,只是如果没怎么接触过算法这一块,或者没怎么接触过链表的使用,其实一时还是不知道怎么入手比较好,大家可以看到这里,别往下看,先思考一下,看是否有思路,尝试自己写一下,看20分钟是否能比较好的完成这道题,做出来是一回事,既然是算法,还要关注它的时间复杂度和空间复杂度哦~
那实际上,稍微分析一下题目就很容易想到一种思路,两个链表都是递增的,要求合并它们,合并之后仍然是递增有序的,那我们可以逐个拿第二个链表的元素和第一个链表的元素去比较,找到一个合适的位置,插入到第一个链表中去,最后合并的链表就是第一个链表,然后再想办法找到第一个链表的表头返回即可。
话是这么说,但是实际写代码的时候,如果完全不引入变量的话,你会发现不是那么好处理,其实上面那个思路咱们可以稍微转换一下,那就是如果我有第三个链表head,然后我分别拿第一个链表head1的val和第二个链表head2的val比较,如果head1.val<head2.val,我就把head1放入到head里面去,然后再拿head1的下一个元素next的val去和刚刚的head2.val去比较,依然看谁大谁小,把小的放入head的下一个元素next中去,一直这样进行下去,知道head1或者head2遍历完成,剩下还没遍历完的就直接挂到head那个链表上去就好了。
好,大体思路相信大家都理解了,可以自己尝试一下。接下来咱们把思路步骤列出来并具体的代码给实现出来。
- 题目要求返回合并之后的表头,我们需要定义好一个虚拟表头head,因为如果不定义好,最后排完序我们的链表指针到尾部去了;
- 定义当前节点cur,初始化指向虚拟表头;
- 开始遍历head1和head2,循环条件是head1!=null && head2!=null;
- 比较head1.val和head2.val,哪个小,就把哪个元素赋值给cur.next,并把小的链表那个指针下移,当前节点也下移
- 剩余元素处理,最后看head1和head2那个链表还有剩余元素,因为它们不会同时遍历完,要么head1先遍历完,要么head2先遍历完,把没有遍历完的挂到cur的下一个元素即可,因为本身是有序的。
- 返回链表头节点,因为第一个节点是我们自己虚拟的,head.next才是我们合并完成之后的头节点。
看下面这个图更好理解:
代码实现
public class ListNode {
int val;
ListNode next;
ListNode(int x) { val = x; }
}
class Solution {
public ListNode mergeTwoLists(ListNode head1, ListNode head2) {
//to do this
//1、定义好一个虚拟节点,初始值可设置为0
ListNode head = new ListNode(0);
//2、定义一个链表来放head1和head1的元素,初始值就等于head
ListNode cur = head;
//3、遍历head1和head2
while(head1!=null && head2!=null){
//4、比较head1.val和head2.val,哪个小,就把哪个元素赋值给cur.next,并把小的链表那个指针下移
if(head1.val<=head2.val){
cur.next = head1;
head1 = head1.next;
}else{
cur.next = head2;
head2 = head2.next;
}
//当前节点也下移
cur = cur.next;
}
//5、剩余元素处理
cur.next = head1==null ? head2:head1;
//6、返回链表头节点
return head.next;
}
//测试一下
public static void main(String[] args){
//构建两个链表
ListNode l1 = new ListNode(1);
l1.next = new ListNode(2);
l1.next.next = new ListNode(4);
ListNode l2 = new ListNode(1);
l2.next = new ListNode(3);
l2.next.next = new ListNode(4);
ListNode head = new Solution().mergeTwoLists(l1,l2);
StringBuilder sb = new StringBuilder();
while(head!=null){
sb.append(head.val);
head = head.next;
if(head!=null){
sb.append("->");
}
}
System.out.println(sb.toString());
}
}
输出结果:
1->1->2->3->4->4
复杂度分析: 时间复杂度 O(M+N):M,N 分别为链表的长度,合并操作需遍历两链表。 空间复杂度O(1) : 节点引用 head , cur使用常数大小的额外空间。
所有总体效果还是不错的,至少时间复杂度不是O(N^2),是一个线性阶,也只额外引入一个节点引用。
你做出来了吗?可能大家都做出来了,或许比我这个实现更好~
这里顺便给大家推荐两个学习算法的网站:
力扣:https://leetcode-cn.com/
牛客网:https://www.nowcoder.com/
- 上一篇: 我的百度面经(共8次面试) 百度面试好过吗
- 下一篇: 百度2023届暑期实习生面经-产品运营岗
猜你喜欢
- 2024-12-29 Java 知识点整理:Spring、MySQL java中的spring
- 2024-12-29 互联网大厂是如何使用牛客网提高面试效率的
- 2024-12-29 LightGBM最强解析,从算法原理到代码实现
- 2024-12-29 百度2023届暑期实习生面经-产品运营岗
- 2024-12-29 我的百度面经(共8次面试) 百度面试好过吗
- 2024-12-29 C++ 学习笔记 c++全套教程
- 2024-12-29 字节跳动实习面试:三面无修改公开,看看他通过了吗?
- 2024-12-29 死锁的 4 种排查工具 死锁的处理方法
- 最近发表
- 标签列表
-
- newcoder (56)
- 字符串的长度是指 (45)
- drawcontours()参数说明 (60)
- unsignedshortint (59)
- postman并发请求 (47)
- python列表删除 (50)
- 左程云什么水平 (56)
- 计算机网络的拓扑结构是指() (45)
- 稳压管的稳压区是工作在什么区 (45)
- 编程题 (64)
- postgresql默认端口 (66)
- 数据库的概念模型独立于 (48)
- 产生系统死锁的原因可能是由于 (51)
- 数据库中只存放视图的 (62)
- 在vi中退出不保存的命令是 (53)
- 哪个命令可以将普通用户转换成超级用户 (49)
- noscript标签的作用 (48)
- 联合利华网申 (49)
- swagger和postman (46)
- 结构化程序设计主要强调 (53)
- 172.1 (57)
- apipostwebsocket (47)
- 唯品会后台 (61)
- 简历助手 (56)
- offshow (61)