单链表的解题思路

六种单链表的解题思想

合并两个有序链表

题目:

在这里插入图片描述

解题思路:

我们想让两个有序链表合并并且合并之后的链表仍为有序链表,就需要我们在合并的时候进行排序,首先创建一个临时结点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;
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值