单链表基础题目

本文详细解析了单链表操作的五道经典题目,包括删除重复节点、判断回文链表、寻找两个链表的公共节点、判断链表是否有环以及找到链表环的起始节点。通过示例和图解,阐述了每种问题的解决思路和关键代码实现,帮助读者深入理解链表操作技巧。
摘要由CSDN通过智能技术生成

单链表题目

第七题删除重复的节点

删除重复的节点

题目大意是一个单链表中存在重复的节点,我们需要将重复的节点删除

样例:
在这里插入图片描述
看到这个样例我们知道,删除重复的节点之后,会生成一个新的链表,所以我们需要重新定义一个链表
在这里插入图片描述
我们可以看着图片来演示这个过程,具体思路就是两个节点,一个节点存的就是要删除的那个节点的前驱,另一个节点就是要删除的节点。

public class Solution {
    public ListNode deleteDuplication(ListNode pHead) {
        ListNode cur = pHead;
        ListNode newHead = new ListNode(-1);
        ListNode tmp = newHead;
        while(cur != null) {
            if(cur.next != null && cur.val == cur.next.val) {
                while(cur.next != null && cur.val == cur.next.val) {
                    cur = cur.next;
                }
                cur = cur.next;
            }else {
                tmp.next = cur;
                cur = cur.next;
                tmp = tmp.next;
            }
        }
        tmp.next = null;
        return newHead.next;
    }
}

太多的细节要考虑了,只有当自己真正的自己演示一遍,才有可能搞懂。

第八题判断链表的回文

判断链表的回文
这题主要思路就是首先找到链表的中间节点,然后让中间节点的后面,都指向前面,一个从前往中间走,一个从后往中间走,如果都一样说明就是回文链表。

1.找到中间节点
2.实现逆置
3.判断是否回文

继续看上面的那个图片
在这里插入图片描述如果链表是奇数的情况就不用说了,但是偶数我们来需要画图来演示
在这里插入图片描述
我们再移动的过程中可以发现,如果是偶数的情况下head.next = slow

public class PalindromeList {
    public boolean chkPalindrome(ListNode A) {
        // write code here
        if(A == null) {
            return true;
        }
        ListNode fast = A;
        ListNode slow = A;
        while(fast != null && fast.next != null) {
            fast = fast.next.next;
            slow = slow.next;//找到中间节点
        }
        ListNode cur = slow.next;
        while(cur != null) {
            ListNode curNext = cur.next;
            cur.next = slow;
            slow = cur;
            cur = curNext;//实现逆置
        }
        while(A != slow) {
            if(A.val != slow.val) {
                return false;
            }
            if(A.next == slow) {
                return true;
            }
            A = A.next;
            slow = slow.next;
        }//判断是否回文
        return true;
    }
}
第九题找到公共节点

找到公共节点

看到这个问题我们应该想到两个地方,
1.这是个Y型,的还是X型的
2.公共节点是值一样,还是地址一样

在这里插入图片描述
从这个图中我们可以看到这是一个Y型的,并且相交的是地址,我们可以看到那个注意保持其原始结构
具体思路是先求出长的链表,比短的多几个长度,然后长的链表走这个长度

1.先求链表A的长度
2.求链表B的长度
3.求出长度差
4.之后继续走判断是否有地址相等的位置

public class Solution {
    public ListNode getIntersectionNode(ListNode headA, ListNode headB) {
        ListNode pl = headA;
        ListNode ps = headB;
        int lenA = 0;
        int lenB = 0;
        while(pl != null) {
            pl = pl.next;
            lenA ++;//找到A的长度
        }
        pl = headA;
        while(ps != null) {
            ps = ps.next;
            lenB ++;//找到B的长度
        }
        ps = headB;
        int len = lenA - lenB;
        if(len < 0) {
            pl = headB;
            ps = headA;
            len = lenB - lenA;//找到长度差
        }
        while(len != 0) {
            pl = pl.next;
            len --;
        }
        while(pl != ps) {
            pl = pl.next;//最后判断是否相等
            ps = ps.next;
        }
        return pl;
    }
}
第十题判断链表是否有环

判断链表是否有环
在这里插入图片描述
这里有个很形象的比喻,就像我们在操场上跑步的场景,如果有环,跑的快的一定可以追上跑的慢的。
我们让其中一个的速度,是另一个速度的2倍。
这里为什么不是3倍呢?
我们看这样一种情况:
在这里插入图片描述
这样的话,速度是3倍是不是永远都满足不了。

public class Solution {
    public boolean hasCycle(ListNode head) {
        ListNode fast = head;
        ListNode slow = head;
        while(fast != null && fast.next != null) {
            fast = fast.next.next;
            slow = slow.next;
            if(fast == slow) {
                return true;
            }
        }
        return false;
    }
}
第十一题找到链表开始如环的第一个节点

找到链表开始如环的第一个节点
还是想到操场的情况,为什么会相遇,只能说明路程是另一个路程的2倍
在这里插入图片描述

之间的关系为:
在这里插入图片描述
化简后可以得到:
在这里插入图片描述
到这里有人问了,你这是只多跑了一圈,后面还有可能多跑了很多圈,其实仔细想想就知道,跑了很多圈只能说明C小,公式还是一样的的。
具体步骤:

1.找到相遇点
2.找到环的节点

public class Solution {
    public ListNode detectCycle(ListNode head) {
        ListNode slow = head;
        ListNode fast = head;
        while(fast != null && fast.next != null) {
            fast = fast.next.next;
            slow = slow.next;
            if(fast == slow) {
                break;
            }
        }
        if(fast == null || fast.next == null) {
            return null;
        }
        fast = head;
        while(fast != slow) {
            fast = fast.next;
            slow = slow.next;
        }
        return fast;
    }
}

本篇文章接上篇文章上篇文章的网址

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值