一.返回倒数第k个节点
建议自己先动手试一试,20分钟做不出来才看解析
题目链接:面试题 02.02. 返回倒数第 k 个节点 - 力扣(LeetCode)
本题目要找的是倒数第k个节点,我们首先要先去讨论一下这个k的合法性。
显然这个k不能小于等于0,同时也不能大于这个链表的长度。
但题目已经保证了给定的k是有效的,所以在本题中可以省去讨论。
有一种做法是先计算链表的长度,然后让该长度减去k值,设减后的值为c
然后从头节点开始走c步,返回走后的节点。
但是这么做的话就需要遍历链表快2遍了,有点麻烦。也不是这道题想要考你的初衷。
我们可以想一下链表的中间节点是怎么找的呢?
是快慢指针的方法,利用fast走完全程时,slow走了一半的特性。此时k为链表长度的一半。
受到启发:我们是不是可以先让fast先走,然后slow和fast一起走,fast走到最后,slow就是倒数第
k个节点。
那么fast应该先走几步呢?
1.如果此时有四个节点,要返回倒数第二个节点。即k=2,即slow要处于第三个节点。
那么就意味着fast要先于slow出发一步。
2.如果此时有六个节点,要返回倒数第三个节点。即k=3,即slow要处于第四个节点。
那么就意味着fast要先于slow2步出发。
上面2个例子,我们可以发现其中的规律:fast先走的步数等于要找的倒数节点数-1,即k-1
明白了这个,这道题就很容易了。
综上:
class Solution {
public int kthToLast(ListNode head, int k) {
ListNode fast=head;
ListNode slow=head;
while(k>1){
if(fast==null){
return -1;
}
fast = fast.next;
k--;
}
while(fast.next!=null){
fast=fast.next;
slow = slow.next;
}
return slow.val;
}
}
二.合并两个有序链表
建议自己先动手试一试,20分钟做不出来才看解析
题目链接:21. 合并两个有序链表 - 力扣(LeetCode)
看到这道题,我相信大多数人的思路都是让2个链表的节点一个一个进行比较,比较完成就将小的
插入到新链表的节点后就行了,直到其中一个链表结束,再将另一个链表的结点插入到新链表之后
我也是这个思路。
我们可以借助一个虚拟结点作为新链表的头节点,这个头节点的值并不重要,因为它只起到了链接
的作用。如下:
ListNode newTmp = new ListNode();
我们要返回新链表的头节点,那就得把它记录下来。
ListNode tmp = newTmp;
在开始之前,我们得确认传参得2个头节点headA,headB是否有效。
综上:
class Solution {
public ListNode mergeTwoLists(ListNode headA, ListNode headB) {
if(headA==null){
return headB;
}
if(headB==null){
return headA;
}
ListNode newH = new ListNode();//虚拟结点,值为多少都无所谓
ListNode tmp = newH;
while(headA!=null && headB!=null){
if(headA.val>headB.val){
tmp.next=headB;
headB = headB.next;
tmp = tmp.next;
} else{
tmp.next=headA;
headA = headA.next;
tmp = tmp.next;
}
}
if(headA==null){
tmp.next = headB;
}
if(headB==null){
tmp.next = headA;
}
return newH.next;
}
}
最后返回newH.next是因为从这里开始才是新链表,不包括newH.next。
三.链表分割
建议自己先动手试一试,20分钟做不出来才看解析
题目链接:链表分割_牛客题霸_牛客网 (nowcoder.com)
这个题我把它分为2个部分。
一部分是把所有小于x的数放在一个链表中,大于等于x放在另一个链表中。再进行链接就好了。
举个例子:x=35
综上:
import java.util.*;
public class Partition {
public ListNode partition(ListNode head, int x) {
//根据x,将链表中的数据划分成两部分
//小于x的部分
ListNode bs=null;
ListNode be=null;
//大于x的部分
ListNode as=null;
ListNode ae=null;
while(head!=null){
//判断当前head的val是哪一部分
if(head.val<x){
//判断是否是第一次插入
if(bs==null){
bs=head;
be=head;
}else{
be.next=head;
be=be.next;
}
head=head.next;
}else{
if(as==null){
as=head;
ae=head;
}else{
ae.next=head;
ae=ae.next;
}
head=head.next;
}
}
第一部分如果为空,返回第二部分 如果第二部分不为空,那么就拼接
if(bs==null){
return as;
}
//进行拼接
be.next=as;
//后半部分不为空,把后半部分最后一个节点置空
if(as!=null){
ae.next=null;
}
return bs;
}
}
如果对你有帮助的话,请给我点点赞吧。