【Java数据结构与算法】链表查找、添加、删除等基础题目及环形链表思路技巧

内含15道链表相关题目解题思路、技巧及题解代码,由简到难。

单链表

每个结点不仅有自己属性,还有指向下一个结点的引用
结点结构:

class ListNode {
    int val;
    ListNode next;

	//构造器
    ListNode() {}
    ListNode(int val) {this.val = val;}
}

链表基本操作:遍历、添加、删除

遍历

我们无法通过所有获取链表第i个元素,必须从头节点逐个遍历
所以链表的查询速度慢,如果我们按照索引来访问元素,时间复杂度为O(N) N为链表长度

添加

如果想在给定结点后面添加新值,我们只需让新值指向给定结点后一个值,再让给定结点指向新值。
所以链表添加速度快。链表添加元素不需要像数组那样将后面所有元素后移。时间复杂度为O(1);

删除

如果我们想删除当前结点,有两种方法

  1. 找到当前节点的上一结点,让上一结点指向当前结点的下一结点。
  2. 让当前结点的值等于下一结点,然后当前结点指向下下结点(无法删除最后一个结点)
    方法1要找到前一结点,需要从头遍历去找,时间复杂度是O(N)
    方法2时间复杂度是O(1) 但是无法删除最后一个结点(杀掉自己的方式就是把自己变成别人,再杀掉别人,细思极恐)

链表基础题目练习:

力扣题目+链接涉及方法+题解链接技巧
二进制链表转整数遍历链表,不断累加,移位,代码
从尾到头打印链表法1.用栈的先入后出特性,法2:将遍历到的数据倒着放入返回的数组
返回倒数第 k 个节点法1:遍历链表得到深度N,倒数第k个即为第N-k个。
法2:让快指针指向第k个,快慢指针一起移动,快指针指向null时慢指针指向倒数第k个结点

快慢指针
链表的中间结点法1:和上面一题方法类似。
法2: 快慢指针,慢指针一次走一步,快指针一次走两步

快慢指针
移除链表元素遍历,发现当前结点下一个结点满足情况,就删除下一个结点,然后移动到下下个结点
删除排序链表中的重复元素因为是排序链表,后一个等于当前时,就把后一个删了,继续比较,不等就移动当前指针
移除重复节点此题链表是没有排序的,移除重复结点得把之前出现得结点保存,发现重复得就移除,代码
删除中间节点不是头节点,也不是尾节点叫做中间节点,用删除自己的方式删除给定节点删除自己
反转链表法1:迭代:让当前元素指向它前一个元素
法2:递归 走到最后,回溯的时候让后一个指向当前,当前置空,返回最后一个结点为新的头 代码
回文链表法1:遍历链表存入数组再左右双指针判断是否回文
法2:先找到链表的最中间结点,然后反转半部分链表,然后遍历比较

环形链表

判断链表中是否有环,返回是否有环

在这里插入图片描述
【哈希表】最直观的方法是把链表存起来,如果遍历到重复的链表就说明有环


【快慢指针】 一个指针速度快,一个指针速度慢,如果有环两个指针一定相遇
原理:Floyd 判圈算法(又称龟兔赛跑算法)
思想:龟兔赛跑,如果没有环,则兔子一直在前面,如果有环,当它们都到环上的时候,由于兔子速度快,兔子一定能套乌龟几圈以后“追上”乌龟。
题目:环形链表
Java代码:

public class Solution {
    public boolean hasCycle(ListNode head) {
        if(head == null || head.next == null) return false;
        ListNode fast = head.next.next, slow = head;
        while(fast != slow) {
            if(fast == null || fast.next == null) return false;
            fast = fast.next.next;
            slow = slow.next;
        }
        return true;
    }
}

判断环的长度

当他们相遇以后,固定一个,另一个再跑一圈并计数,当他们再次相遇的时候,可以得到环的大小。

判断环的入口

假设进入环之前的长度是a,环入口到相遇点距离是b,相遇点到环入口距离是c,如下图所示
请添加图片描述
由于快指针fast速度是慢指针slow的两倍,如果同时入环,fast是在入环处再次与slow相遇,而fast比slow先入环所以在slow走完一环的时间内,fast一定能追上slow。
所以slow 走过的路程是 a + b,fast走过的路程是 a + b +n(b + c) 两个式子的关系是:时间相同,速度两倍。
在这里插入图片描述
由这个公式可以发现, a的距离和n圈+c的距离相等,也就是:
如果我们拿一个从头开始的指针str 和相遇后的slow指针一起按照同样的速度走,当str走到环入口时,刚好slow走了n-1圈+c的距离,与str相遇

题目:环形链表Ⅱ:返回环入口

public class Solution {
    public ListNode detectCycle(ListNode head) {
        if(head == null || head.next == null) return null;
        ListNode fast = head,slow = head;//同时开始
        while(fast != null) {
            if(fast.next == null) return null;
            fast = fast.next.next;
            slow = slow.next;
            if(fast == slow) { //相遇了   
                ListNode str = head;
                while(str != slow) {
                    str= str.next;
                    slow = slow.next;
                }
                 return str;
            }
        }
        return null;
    }
}

进阶题目

题目+链接思路技巧
链表中的两数相加先把两个链表反转,然后模拟加法,然后把结果链表再反转回来链表反转
重排链表法1:将链表分割成两部分,反转后半部分,然后合并链表
法2:将链表结点存入List中,第一个指向最后一个,再移动指针。不要忘记链表末尾置空。题解代码
排序的循环列表先找到最大的结点,然后分情况讨论即可,题解代码
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

甲 烷

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值