今天要解决四道关于链表的常规题,点击链接直达力扣,冲冲冲!🤪
L1 删除链表的节点
基础题,双指针一前一后。注意删除头节点 + 空节点。
此题对比原题有改动,但难度系数其实是相同的,都是考查删除节点的基本功,只不过原题直接告诉了要删除的节点,不用找了,所以是O(1)的。
时间复杂度:O(n)
空间复杂度:O(1)
/**
* Definition for singly-linked list.
* public class ListNode {
* int val;
* ListNode next;
* ListNode(int x) { val = x; }
* }
*/
class Solution {
public ListNode deleteNode(ListNode head, int val) {
if(head==null){
return null;
}
if(head.val==val){
return head.next;
}
ListNode cur=head.next;
ListNode pre=head;
while(cur!=null){
if(cur.val==val){
pre.next=cur.next;
return head;
}
pre=pre.next;
cur=cur.next;
}
return head;
}
}
L2 链表中倒数第K个节点
基础题,快慢指针。注意起点是1还是0。
时间复杂度:O(n)
空间复杂度:O(1)
/**
* 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 trainingPlan(ListNode head, int cnt) {
ListNode fast=head;
ListNode slow=head;
while(cnt>0){
fast=fast.next;
cnt--;
}
while(fast!=null){
slow=slow.next;
fast=fast.next;
}
return slow;
}
}
L3 合并两个排序的链表
常规题,拉拉链。注意最后没排完的链表可以直接连上,不用一个个节点接上。
时间复杂度:O(n+m),n 和 m 表示两个链表长度
空间复杂度:O(1)
/**
* 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 trainningPlan(ListNode l1, ListNode l2) {
ListNode dummy=new ListNode(-1);
ListNode p1=l1,p2=l2;
ListNode cur=dummy;
while(p1!=null&&p2!=null){
if(p1.val<=p2.val){
cur.next=p1;
p1=p1.next;
}else{
cur.next=p2;
p2=p2.next;
}
cur=cur.next;
}
if(p1!=null){
cur.next=p1;
}
if(p2!=null){
cur.next=p2;
}
return dummy.next;
}
}
L4 两个链表的第一个公共点
由于本题是不存在环的,所以相对容易,可以直接遍历计算节点数量之差,也可以采用双指针,不过建议理解双指针的方法,代码优雅。
时间复杂度:O(n+m),n 和 m 表示两个链表长度
空间复杂度:O(1)
/**
* Definition for singly-linked list.
* public class ListNode {
* int val;
* ListNode next;
* ListNode(int x) {
* val = x;
* next = null;
* }
* }
*/
class Solution {
ListNode getIntersectionNode(ListNode headA, ListNode headB) {
if(headA==null||headB==null)return null;
ListNode p1=headA,p2=headB;
while(p1!=p2){
p1= p1==null?headB:p1.next;
p2= p2==null?headA:p2.next;
}
return p1;
}
}
总结
链表的技巧,老生常谈了哈。就那么两点:双指针(包括快慢指针、左右指针...)、虚拟头节点。
如果本文对你有帮助的话,不妨点个小赞👍帮助更多的小伙伴!!!