4、在链表中穿针引线

内容来自刘宇波老师玩转算法面试

1、在节点间穿针引线

206 - 反转链表

image
image

/**
 * 非递归实现
 * 最终状态如下
 * cur、next -> null
 * prev -> newHead
 */
public static ListNode reverseList1(ListNode head) {
    ListNode prev = null;
    ListNode cur = head;
    ListNode next;
    while (cur != null) {
        next = cur.next;
        cur.next = prev;
        prev = cur;
        cur = next;
    }

    return prev;
}

/**
 * 递归: 反转以 head 为头的链表, 并返回新的头结点
 */
public static ListNode reverseList2(ListNode head) {
    if (head == null || head.next == null) return head;

    ListNode newHead = reverseList2(head.next);
    head.next.next = head;
    head.next = null;

    return newHead;
}

更多问题
92 - 反转链表 II

2、测试你的链表程序

public class ListNode {

    public int val;
    public ListNode next;

    public ListNode() {
    }

    public ListNode(int val) {
        this(val, null);
    }

    public ListNode(int val, ListNode next) {
        this.val = val;
        this.next = next;
    }

    public ListNode(int[] arr) {
        if (arr == null || arr.length == 0) throw new IllegalArgumentException("Arr is empty.");

        this.val = arr[0];
        ListNode cur = this;
        for (int i = 1; i < arr.length; i++) {
            cur.next = new ListNode(arr[i]);
            cur = cur.next;
        }
    }

    @Override
    public String toString() {
        StringBuilder sb = new StringBuilder();
        ListNode cur = this;
        while (cur != null) {
            sb.append(cur.val).append("->");
            cur = cur.next;
        }
        sb.append("NULL");
        return sb.toString();
    }
}

更多问题
83 - 删除排序链表中的重复元素
86 - 分隔链表
328 - 奇偶链表
2 - 两数相加
445 - 两数相加 II

3、设立链表的虚拟头结点

203 - 移除链表元素

image

/**
 * 不使用 dummyHead
 */
public static ListNode removeElements1(ListNode head, int val) {
    // 1.先删除符合条件的头结点
    while (head != null && head.val == val) head = head.next;
    if (head == null) return null;

    // 2.再删除其他节点
    ListNode prev = head;
    while (prev.next != null) {
        if (prev.next.val == val) prev.next = prev.next.next;
        else prev = prev.next;
    }

    return head;
}

/**
 * 使用 dummyHead
 */
public static ListNode removeElements2(ListNode head, int val) {
    ListNode dummyHead = new ListNode(-1, head);

    ListNode prev = dummyHead;
    while (prev.next != null) {
        if (prev.next.val == val) prev.next = prev.next.next;
        else prev = prev.next;
    }

    return dummyHead.next;
}

/**
 * 递归解决问题
 */
public static ListNode removeElements3(ListNode head, int val) {
    if (head == null) return null;
    head.next = removeElements3(head.next, val);
    return head.val == val ? head.next : head;
}

更多问题
82 - 删除排序链表中的重复元素 II
21 - 合并两个有序链表

4、复杂的穿针引线

24 - 两两交换链表中的节点

image
image

public static ListNode swapPairs1(ListNode head) {
    if (head == null || head.next == null) return head;
    ListNode dummyHead = new ListNode(-1, head);

    // 1 -> 2 -> 3 -> 4 -> 5 -> 6
    // 2 -> 1 -> 4 -> 3 -> 6 -> 5
    ListNode prev = dummyHead;
    ListNode node1 = head;
    ListNode node2 = head.next;
    ListNode next;
    while (node1 != null && node2 != null) {
        next = node2.next;
        node2.next = node1;
        node1.next = next;
        prev.next = node2;

        prev = node1;
        node1 = next;
        if (node1 != null) node2 = node1.next;
    }

    return dummyHead.next;
}

public static ListNode swapPairs2(ListNode head) {
    if (head == null || head.next == null) return head;

    // 1 -> 2 -> 3 -> 4 -> 5 -> 6
    // 2 -> 1 -> 4 -> 3 -> 6 -> 5
    ListNode node = swapPairs2(head.next.next);
    ListNode newHead = head.next;
    newHead.next = head;
    head.next = node;

    return newHead;
}

更多问题
25 - K 个一组翻转链表
147 - 对链表进行插入排序
148 - 排序链表

5、不仅仅是穿针引线

237 - 删除链表中的节点

public void deleteNode(ListNode node) {
    node.val = node.next.val;
    node.next = node.next.next;
}

6、双指针技术

19 - 删除链表的倒数第 N 个结点

image

public static ListNode removeNthFromEnd(ListNode head, int n) {
    ListNode dummyHead = new ListNode(-1, head);

    ListNode p = dummyHead;
    ListNode q = p;
    // 让 q 向后移动 n + 1 次
    for (int i = 0; i < n + 1; i++) {
        if (q == null) return head;
        q = q.next;
    }

    while (q != null) {
        p = p.next;
        q = q.next;
    }

    p.next = p.next.next;
    return dummyHead.next;
}

更多问题
61 - 旋转链表
143 - 重排链表
234 - 回文链表

posted @ 2023-05-11 08:54  lidongdongdong~  阅读(13)  评论(0编辑  收藏  举报