链表理论基础下:6月13日

46 阅读3分钟

1:两两交换链表中的节点

解法1:不带虚节点

刚开始的思路是不带虚节点 。有点混乱。

/**
 * 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 head;
            }

            ListNode cur = head;
            ListNode after = cur.next;
            ListNode result;

            if(after != null){
                result = after;
            }
            else {
                result = cur;
            }

            while(cur!= null && after !=null){

                ListNode temp = after.next;
                after.next = cur;

                if(temp != null && temp.next != null){
                    after = temp.next;
                }
                else if(temp != null && temp.next == null){
                    cur.next = temp;
                    break;
                }
                else {
                    after = null;
                }

                //这里上一个cur要指向下一个after
                cur.next = after;
                cur = temp;

            }
            return result;

    }
}

解法二:带虚节点

TODO

2:删除链表的倒数第N个节点

定义双指针i和j,j首先向后移动n位,ij同时后移,i即倒数第n个节点 这里有两种解法,第一种是j最后指向链表最后一个结点,第二种是可以将j指向最后一个结点的后一个

第一种

/**
 * 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 removeNthFromEnd(ListNode head, int n) {
        ListNode dummy = new ListNode(-1,head);
        ListNode slow = dummy, fast = dummy;
        while(n > 0 && fast.next != null){
            fast = fast.next;
            n--;
        }
        while(fast.next != null){
            fast = fast.next;
            slow = slow.next;
        }
        slow.next = slow.next.next;
        return dummy.next;
    }
}

第二种


class Solution {
    public ListNode removeNthFromEnd(ListNode head, int n) {
        //新建一个虚拟头节点指向head
        ListNode dummyNode = new ListNode(0);
        dummyNode.next = head;
        //快慢指针指向虚拟头节点
        ListNode fastIndex = dummyNode;
        ListNode slowIndex = dummyNode;

        // 只要快慢指针相差 n 个结点即可
        for (int i = 0; i <= n; i++) {
            fastIndex = fastIndex.next;
        }
        while (fastIndex != null) {
            fastIndex = fastIndex.next;
            slowIndex = slowIndex.next;
        }

        // 此时 slowIndex 的位置就是待删除元素的前一个位置。
        // 具体情况可自己画一个链表长度为 3 的图来模拟代码来理解
        // 检查 slowIndex.next 是否为 null,以避免空指针异常
        if (slowIndex.next != null) {
            slowIndex.next = slowIndex.next.next;
        }
        return dummyNode.next;
    }
}

3:链表相交

简单来说,就是求两个链表交点节点的指针。 这里同学们要注意,交点不是数值相等,而是指针相等。

为了方便举例,假设节点元素数值相等,则节点指针相等。

看如下两个链表,目前curA指向链表A的头结点,curB指向链表B的头结点:

面试题02.07.链表相交_1

我们求出两个链表的长度,并求出两个链表长度的差值,然后让curA移动到,和curB 末尾对齐的位置,如图:

面试题02.07.链表相交_2

此时我们就可以比较curA和curB是否相同,如果不相同,同时向后移动curA和curB,如果遇到curA == curB,则找到交点。

否则循环退出返回空指针。

/**
 * 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) {
        int lena= 0, lenb= 0;
            ListNode curA = headA, curB = headB;
            while(curA!= null){
                lena++;
                curA = curA.next;
            }
            while(curB != null){
                lenb++;
                curB = curB.next;
            }
            int abs = (lena - lenb) > 0 ? (lena - lenb) : -(lena - lenb);
            curA = headA;
            curB = headB;
            if(lena > lenb){
                while(abs > 0){
                    curA = curA.next;
                    abs--;
                }
            }
            else{
                while(abs > 0){
                    curB = curB.next;
                    abs--;
                }
            }
            while(curA != null && curB != null){
                if(curA == curB){
                    return curA;
                }
                curA = curA.next;
                curB = curB.next;
            }
            return null;
    }
}

4:环形链表II

方法一:哈希表

/**
 * 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) {
        Map<ListNode,Integer> map = new HashMap<>();
        ListNode cur = head;
        while(cur != null){
            map.put(cur,map.getOrDefault(cur,0) + 1);
            if(map.get(cur) > 1){
                return cur;
            }
            cur = cur.next;
        }
        return null;
        
    }
}

方法二:快慢指针法

TODO