文章目录
六种单链表的解题思想
合并两个有序链表
题目:
解题思路:
我们想让两个有序链表合并并且合并之后的链表仍为有序链表,就需要我们在合并的时候进行排序,首先创建一个临时结点dummy为-1,创建一个临时节点p为dummy,然后将排好序的节点依次放在p之后, 最后把两个链表中没有用完的依次添加在p之后
代码如下:
/**
* 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 mergeTwoLists(ListNode list1, ListNode list2) {
ListNode dummy =new ListNode(-1),p = dummy;
ListNode p1 = list1, p2 = list2;
while(p1!=null&&p2!=null){
//对p1和p2现在节点的值进行比较
//将小的值拼接在p上
if(p1.val<p2.val){
p.next = p1;
p1 = p1.next;
}else{
p.next = p2;
p2 = p2.next;
}
p = p.next;
}
//将多余出来的剩余节点并在链表后面
if(p1!=null){
p.next = p1;
}
if(p2!=null){
p.next = p2;
}
return dummy.next;
}
}
单链表的倒数第 k 个节点
题目:
解题思路:
双指针思想,我们如果想找倒数第k个,可以定义两个节点p1,p2同时为head,我们先让p1走k步,然后同时让p1,p2走n-k步,这时候的p2就是倒数第k个节点了
代码如下:
class Solution {
public ListNode removeNthFromEnd(ListNode head, int n) {
//我们如果想删除倒数第k个节点,就需要删除倒数第k+1个节点
//定义一个dummy节点为第一个节点,这样从head节点到最后的节点,他们的倒数第一个节点就不会为空了
ListNode dummy = new ListNode(-1);
dummy.next = head;
//这里应该是dummy多出一个辅助节点
ListNode p1 = dummy;
//这里先找倒数(k+1)个节点就让p1先走k+1步
for(int i = 0;i<n+1;i++){
p1 = p1.next;
}
ListNode p2 = dummy;
while(p1!=null){
p1 = p1.next;
p2 = p2.next;
}
p2.next = p2.next.next;
return dummy.next;
}
}
链表的中间节点
题目:
解题思路:
设置快慢节点,让fast指针和head指针的起始点都在head,但是每次让快节点走两步,慢节点走一步
代码如下:
class Solution {
public ListNode middleNode(ListNode head) {
//快慢节点
ListNode slow = head, fast = head;
while(fast != null && fast.next!=null){
slow = slow.next;
if(fast.next.next == null){
fast = fast.next;
}else{
fast = fast.next.next;
}
}
return slow;
}
}
判断链表是否包括环
题目:
解题思路:
还是快慢节点,如果里面有环那么快节点一定能追上慢节点,如果没有环,那么就追不到,代码很简单
代码如下:
public class Solution {
public boolean hasCycle(ListNode head) {
ListNode slow = head, fast = head;
while(fast!=null && fast.next!=null){
fast = fast.next.next;
slow = slow.next;
while(slow == fast){
return true;
}
}
return false;
}
}
环形链表 II
题目:
解题思路:
这个题是要我们找环的开始点,我们同样定义快慢指针,快指针走了2k,慢指针走了k,我们设环起点和相遇点距离为m,这时候head里环起点距离为k-m,同样相遇点与环起点的优弧路径也为k-m
代码如下:
public class Solution {
public ListNode detectCycle(ListNode head) {
ListNode fast = head, slow = head;
while(fast!=null && fast.next != null){
//如果碰面了
//或者没有环也就是fast为空就返回
fast = fast.next.next;
slow = slow.next;
if(slow == fast){
break;
}
}
if(fast == null || fast.next == null){
return null;
}
//让slow指针调回head然后再走一圈
fast = head;
//判断条件是如果slow碰不到fast,就让slow和fast一直走
while(slow != fast){
slow = slow.next;
fast = fast.next;
}
return fast;
}
}
判断两个链表是否相交
题目:
解题思路:
我们设A相同端(a1->a2)为a,B相同端(b1->b2->b3)为b,A与B相同端(c1->c2->c3)为c,
则有a+c+b+c = b + c + a +c (也就是让A拼接上B,让B拼接上A 如果有相同的,那么他们最后必相交于c)
代码如下:
public class Solution {
public ListNode getIntersectionNode(ListNode headA, ListNode headB) {
// p1 指向 A 链表头结点,p2 指向 B 链表头结点
ListNode p1 = headA, p2 = headB;
while (p1 != p2) {
if(p1 == null) p1 = headB;
else p1 = p1.next;
if(p2 == null) p2 = headA;
else p2 = p2.next;
}
return p1;
}
}