java 单链表和双_Java单链表链表中的双指针

JJava单链表链表中的双指针

前言

1. 链表环检测

1.1 思路

1.2 代码

2. 找环入口

2.1 思路

2.2 代码

3. 删除链表倒数第n个结点

3.1 思路

3.2 代码

4. 回文链表

4.1 思路

4.2 代码

总结

前言

链表的很多操作都使用了双指针的思路,今天简单记录几个常用的单链表操作。

下面这段代码是这篇文章中链表的基本结构。

class ListNode {

int val;

ListNode next;

ListNode(int x) {

val = x;

next = null;

}

}

1. 链表环检测

链表中的环简单来说就是链表最后一个结点的next指针并不是null,而是指向了链表中的某一个结点,形成了一个环。

1.1 思路

使用两个指针,第一个指针每次向后走一个结点,第二个指针每次向后走两个结点。如果没有环,第二个指针将先指向最后一个结点或者指向最后结点的next。如果有环,第一个指针与第二个指针将在环中相遇。

1.2 代码

public boolean hasCycle(ListNode head) {

if (head == null || head.next == null || head.next.next == null) {

return false;

}

ListNode slow = head;

ListNode fast = head.next.next;

while (fast != null && fast.next != null) {

slow = slow.next;

fast = fast.next.next;

if (slow == fast) {

return true;

}

}

return false;

}

2. 找环入口

如果链表存在环,找到链表的环入口。也就是最后一个结点指向的结点。

2.1 思路

使用两个指针,第一个指针每次向后走一个结点,第二个指针每次向后走两个结点。如果没有环,第二个指针将先指向最后一个结点或者指向最后结点的next,返回null,如果有环,第一个指针与第二个指针将在环中相遇,相遇后,将其中一个指针执行head,每次向后走一个结点,另个指针从第一次相遇结点每次向后走一个结点,当两个指针再次相遇时,就是环入口。

2.2 代码

public ListNode detectCycle(ListNode head) {

if (head == null || head.next == null || head.next.next == null) {

return null;

}

ListNode slow = head;

ListNode fast = head;

while (fast != null && fast.next != null) {

slow = slow.next;

fast = fast.next.next;

if (slow == fast) {

slow = head;

while (slow != fast) {

slow = slow.next;

fast = fast.next;

}

return slow;

}

}

return null;

}

3. 删除链表倒数第n个结点

先决条件,给定的n是有效的。

3.1 思路

声明一个哨兵结点,将哨兵结点的next指针指向head;两个指针同时指向哨兵结点,第一个指针先向后走n步,之后两个指针同时向后遍历,当第一个指针为null时,第二个指针的next结点就是链表倒数第n个结点,将其删除。返回哨兵结点的next结点,也就是链表的头结点。

3.2 代码

public ListNode removeNthFromEnd(ListNode head, int n) {

if(head == null){

return head;

}

ListNode sentry=new ListNode(0);

sentry.next=head;

ListNode prevNode = sentry;

ListNode currNode = sentry;

for(int i = 0;i <= n; i++){

currNode = currNode.next;

}

while(currNode!=null){

currNode = currNode.next;

prevNode = prevNode.next;

}

prevNode.next = prevNode.next.next;

return sentry.next;

}

4. 回文链表

判断一个链表是否是回文链表。

4.1 思路

还是需要两个指针,第一个指针每次向后走一个结点,第二个指针每次向后走两个结点,同时还需要一个指针指向第一个指针的前一个结点,当第二个指针是最后一个结点的时候,或者说找到中间结点时,需要根据第一个指针的前置结点将链表分成两段,然后翻转后半部分的链表,在将两个链表逐个对比。

4.2 代码

public boolean isPalindrome(ListNode head) {

if (head == null || head.next == null) {

return true;

}

//慢指针前置结点

ListNode slowPrev = head;

//慢指针

ListNode slow = slowPrev.next;

//快指针

ListNode fast = slow.next;

//找中间结点

while (fast != null && fast.next != null) {

slowPrev = slow;

slow = slow.next;

fast = fast.next.next;

}

//分成两段

if (slowPrev != null) {

slowPrev.next = null;

}

//翻转后半部分的链表

slowPrev = null;

while (slow != null) {

ListNode temp = slow.next;

slow.next = slowPrev;

slowPrev = slow;

slow = temp;

}

//两个链表逐个对比

while (head != null && slowPrev != null) {

if (head.val != slowPrev.val) {

return false;

}

head = head.next;

slowPrev = slowPrev.next;

}

return true;

}

总结

链表的操作还有很多,LeetCode上有很多题,没事看一看,学习的不是代码,是思路。

            ad002be7b18ff33ef2be391164340436.png

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Android是一种基于Linux内核(不包含GNU组件)的自由及开放源代码的移动操作系统,主要应用于移动设备,如智能手机和平板电脑。该系统最初由安迪·鲁宾开发,后被Google公司收购并注资,随后与多家硬件制造商、软件开发商及电信营运商共同研发改良。 Android操作系统的特点包括: 开放源代码:Android系统采用开放源代码模式,允许开发者自由访问、修改和定制操作系统,这促进了技术的创新和发展,使得Android系统具有高度的灵活性和可定制性。 多任务处理:Android允许用户同时运行多个应用程序,并且可以轻松地在不同应用程序之间切换,提高了效率和便利性。 丰富的应用生态系统:Android系统拥有庞大的应用程序生态系统,用户可以从Google Play商店或其他第三方应用市场下载和安装各种各样的应用程序,满足各种需求。 可定制性:Android操作系统可以根据用户的个人喜好进行定制,用户可以更改主题、小部件和图标等,以使其界面更符合个人风格和偏好。 多种设备支持:Android操作系统可以运行在多种不同类型的设备上,包括手机、平板电脑、智能电视、汽车导航系统等。 此外,Android系统还有一些常见的问题,如应用崩溃、电池耗电过快、Wi-Fi连接问题、存储空间不足、更新问题等。针对这些问题,用户可以尝试一些基本的解决方法,如清除应用缓存和数据、降低屏幕亮度、关闭没有使用的连接和传感器、限制后台运行的应用、删除不需要的文件和应用等。 随着Android系统的不断发展,其功能和性能也在不断提升。例如,最新的Android版本引入了更多的安全性和隐私保护功能,以及更流畅的用户界面和更强大的性能。此外,Android系统也在不断探索新的应用场景,如智能家居、虚拟现实、人工智能等领域。 总之,Android系统是一种功能强大、灵活可定制、拥有丰富应用生态系统的移动操作系统,在全球范围内拥有广泛的用户基础。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值