链表作为数据结构的重要知识点,通常作为大厂们笔试面试题,这里我写了两篇博客来解决,一共10道题,此篇为前五道题。
下篇博客: 后五道题
目录
3.给定一个带有头结点 head 的非空单链表,返回链表的中间结点。如果有两个中间结点,则返回第二个中间结点。
5. 将两个有序链表合并为一个新的有序链表并返回。新链表是通过拼接给定的两个链表的所有节点组成的。
1. 删除链表中等于给定值 val 的所有节点。
public ListNode removeElements(ListNode head, int val) {
if(head==null){
return null;
}
ListNode prev=head;
ListNode cur=prev.next;
while(cur!=null){
if(cur.val==val){
prev.next=cur.next;
cur=cur.next;
}else {
cur=cur.next;
prev=prev.next;
}
}
if(head.val==val){
head=head.next;
}
return head;
}
方法很简单,主要是对链表便利一遍,节点的val值与给定值相同删除即可,需要注意的是你删除链表节点时需要将现在节点的前驱和后驱进行修改,后驱非常容易获得,前驱就需要我们定义出来,然后定义cur便利数组,由于有前驱的存在,我们从head的下一个节点开始便利,最后对head的值·进行判断即可。
2. 反转一个单链表。
public ListNode reverseList(ListNode head) {
if (head == null) {
return null;
}
ListNode cur = head;
ListNode curNext = cur.next;
head.next = null;
while (curNext != null) {
head = curNext;
curNext = curNext.next;
head.next = cur;
cur = head;
}
return head;
}
要反转我们先把head的next值变为null,在定义cur和curnext,由于翻转可能会丢失后面的几点,所以我们需要定义一个curnext来放置丢失。进入循环先让head往后走一步,再将curnext往后走一步,然后把head的next改为cur,最后cur走到head的位置上。
3.给定一个带有头结点 head 的非空单链表,返回链表的中间结点。如果有两个中间结点,则返回第二个中间结点。
public ListNode middleNode(ListNode head) {
ListNode fast = head;
ListNode slow = head;
while (fast != null && fast.next != null) {
fast = fast.next.next;
slow = slow.next;
}
return slow;
}
找链表的中间节点时,我们需要定义两个节点,一个快节点,一次走两步,一个慢节点一次走一步,当快节点走到尾部时,慢节点刚好位于中间。
4. 输入一个链表,输出该链表中倒数第k个结点。
public ListNode findKthToTail(ListNode head,int k) {
//k是否是合法的
if (k <= 0 || head == null) {
return null;
}
ListNode fast = head;
ListNode slow = head;
while (k - 1 > 0) {
fast = fast.next;
k--;
if (fast == null) {
return null;
}
}
while (fast.next != null) {
fast = fast.next;
slow = slow.next;
}
return slow;
}
首先我们要对k的值还有head进行合法性检验。找到倒数第k个,我们还是第一两个节点,让fast先走k减一步,再让他两一起走,fast到达最后一个时,slow正好是倒数第k个。注意,fast先走时,如果fast直接走到最后了说明k值过大,返回null。
5. 将两个有序链表合并为一个新的有序链表并返回。新链表是通过拼接给定的两个链表的所有节点组成的。
public ListNode mergeTwoLists(ListNode list1, ListNode list2) {
ListNode newNode=new ListNode(-1);
ListNode tmp=newNode;
while (list1!=null&&list2!=null){
if(list1.val<list2.val){
tmp.next=list1;
tmp=tmp.next;
list1=list1.next;
}else {
tmp.next=list2;
tmp=tmp.next;
list2=list2.next;
}
}
if(list1!=null){
tmp.next=list1;
}
if(list2!=null){
tmp.next=list2;
}
return newNode.next;
}
要将两个链表拼接为一个有序的输出,首先我们定义一个虚拟的头结点,永远位于头部,再用tmp节点同时便利两个链表,哪个小就把哪个往上拼接即可,知道他两其中一个为空,再分别进行判断,如果不为空,说明是另外一个先走完,直接把剩余的拼接上即可,需要注意的是,如果list1的val值小就list1走,list2不走,而不是两个同时走,这样才能全部比较。