【小嘟陪你刷题08】二进制链表转整数、从尾到头打印链表、两两交换链表中的节点、相交链表、环形链表

一、二进制链表转整数

在这里插入图片描述

1.1 迭代

创建一个节点cur去遍历链表,实现每个节点的值二进制转整数

1.2 代码展示

/**
 * 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 int getDecimalValue(ListNode head) {
        ListNode cur = head;
        int ret = 0;
        while (cur != null) {
            ret = cur.val  + ret * 2;
            cur = cur.next;
        }
        return ret;
    }
}

二、从尾到头打印链表

在这里插入图片描述

2.1 辅助栈法

解题思路:
链表特点:只能从前至后访问每个节点

算法流程:

  1. 入栈:遍历,将各节点入栈,使用addLast()
  2. 出栈:将各节点值出栈,存储于数组并返回

2.2 代码展示

/**
 * Definition for singly-linked list.
 * public class ListNode {
 *     int val;
 *     ListNode next;
 *     ListNode(int x) { val = x; }
 * }
 */
class Solution {
    public int[] reversePrint(ListNode head) {
        ListNode cur = head;
        LinkedList<Integer> mid = new LinkedList<>();

        while (cur != null) {
            mid.addLast(cur.val);
            cur = cur.next;
        }
        int[] ret = new int[mid.size()];
        for (int i = 0; i < ret.length; i++) {
            ret[i] = mid.removeLast();
        }
        return ret;
    }
}

三、两两交换链表中的节点

在这里插入图片描述

3.1 迭代

创建tmp节点,每次需要交换tmp后面的两个节点。
如果tmp的后面没有节点,或者只有一个节点,则没有更多的节点需要交换,因此结束交换。否则,获得tmp后面的两个节点node1和node2,通过更新节点的指针关系实现两两交换节点。

tmp.next = node2;
node1.next = node2.next;
node2.next = node1;

在这里插入图片描述
完成上述操作之后两两节点交换之后,令tmp=node1,对链表中的其余节点进行两两交换。最后返回新的链表的头节点即可。

3.2 代码展示

/**
 * 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 swapPairs(ListNode head) {
        if (head == null) return null;
        ListNode dummyHead = new ListNode(0);
        dummyHead.next = head;
        ListNode tmp = dummyHead;
        while (tmp.next != null && tmp.next.next != null) {
            ListNode node1 = tmp.next;
            ListNode node2 = tmp.next.next;
            tmp.next = node2;
            node1.next = node2.next;
            node2.next = node1;
            tmp = node1;
        }
        return dummyHead.next;
    }
}

四、相交链表

在这里插入图片描述

4.1 双指针

只有当链表headA和headB都不为空时,链表才可能相交。

首先判断链表headA和headB是否为空,如果其中至少有一个链表为空,则两个链表一定不相交,返回null。

创建两个指针pl和ps,分别指向两个链表的头节点,然后将两个指针依次遍历两个链表的每个节点。

pl指的是长的链表的节点,ps表示短的链表的节点,所有我们需要设计一个方法来实现将pl永远指向长链表,ps指向短链表。
同时我们可以得到长链表和短链表的差值步,我们让ps走差值步,然后同时走,直到相遇。

4.2 代码展示

/**
 * Definition for singly-linked list.
 * public class ListNode {
 *     int val;
 *     ListNode next;
 *     ListNode(int x) {
 *         val = x;
 *         next = null;
 *     }
 * }
 */
public class Solution {
    public ListNode getIntersectionNode(ListNode headA, ListNode headB) {
        if (headA == null || headB == null) {
            return null;
        }

        ListNode pl = headA;
        ListNode ps = headB;

        int lenA = 0;
        int lenB = 0;

        while (pl != null) {
            lenA++;
            pl = pl.next;
        }
        pl = headA;
        while (ps != null) {
            lenB++;
            ps = ps.next;
        }
        ps = headB;
        int len = lenA - lenB;//差值步
        if (len < 0) {
            pl = headB;
            ps = headA;
            len = lenB - lenA;
        }
        //1. pl 永远指向了最长的链表 ps 永远指向了最短的链表
        //2. 求到了差值len步
        //3. 走差值步
        //同时走,直到相遇
        while (len != 0) {
            pl = pl.next;
            len--;
        }
        while (pl != ps) {
            pl = pl.next;
            ps = ps.next;
        }
        return pl;
    }
}

五、环形链表

5.1 环形链表 I

在这里插入图片描述

5.1.1 快慢指针

我们定义两个指针,一快一慢。慢指针每次只移动一步,而快指针每次移动两步。初始时,慢指针在位置 head,而快指针在位置 head。这样一来,如果在移动的过程中,快指针反过来追上慢指针,就说明该链表为环形链表。否则快指针将到达链表尾部,该链表不为环形链表。

5.1.2 代码展示

/**
 * Definition for singly-linked list.
 * class ListNode {
 *     int val;
 *     ListNode next;
 *     ListNode(int x) {
 *         val = x;
 *         next = null;
 *     }
 * }
 */
public class Solution {
    public boolean hasCycle(ListNode head) {
        if (head == null ) return false;
         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;
    }
}

5.2 环形链表 II

在这里插入图片描述

5.2.1 快慢指针

我们使用两个指针,一快一慢,慢指针每次只移动一步,而快指针每次移动两步。
如果链表中存在环,则fast最终会追上slow相遇。

我们设链表中环外的长度为a,slow进入环后,又走了b步与fast相遇,此时fast已经走完了环的n圈,因此它走过的总距离为a+n(b+c)+b=a+(n+1)nc.
在这里插入图片描述
任意时刻,fast走过的步数时slow的2倍,因此有
在这里插入图片描述
我们可以发现,从相遇点到入环点的距离加上n-1圈的环长,恰好等于从链表头部进入环点的距离。
因此,但发现slow与fast相遇时,相遇点就是入环点。

5.2.2 代码展示

/**
 * Definition for singly-linked list.
 * class ListNode {
 *     int val;
 *     ListNode next;
 *     ListNode(int x) {
 *         val = x;
 *         next = null;
 *     }
 * }
 */
public class Solution {
    public ListNode detectCycle(ListNode head) {
        if (head == null) return null;
        ListNode fast = head;
        ListNode slow = 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;
    }
}
评论 65
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

摸鱼王胖嘟嘟

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

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

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

打赏作者

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

抵扣说明:

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

余额充值