Loading

链表

链表

删除链表元素

Leetcode19.删除链表的倒数第N个节点

问题在于如何定位倒数第n个节点。采用「双指针」。可以先P1从头遍历n个节点,然后再以P2从头开始遍历,直到P1到尾节点。此时P2刚好会落在倒数第n个节点。

代码如下:

/**
 * 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) {
        if(head == null || n == 0) {
            return head;
        }
        // 定义结果
        ListNode result = new ListNode(0, head);
        // pre从head开始遍历
        ListNode pre = head;
        // 从1开始计数,while循环结束后pre刚好指向第n个节点
        int i = 1;
        while(i < n) {
            pre = pre.next;
            i++;
        }
        // cur从result开始遍历。因为要删除倒数第n个节点,所以此处提前一个节点遍历
        ListNode cur = result;
        while(pre.next != null) {
            cur = cur.next;
            pre = pre.next;
        }
        // 删除第n个节点
        cur.next = cur.next.next;
        return result.next;
    }
}

LeetCode82.删除排序链表中的重复元素II

代码如下:

/**
 * 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 deleteDuplicates(ListNode head) {
        if(head == null || head.next == null) {
            return head;
        }
        ListNode result = new ListNode(-1000, head);
        ListNode cur = result;
        // 注意这里的判断
        while(cur.next != null && cur.next.next != null) {
            // 如果存在相等的case,就进入if条件
            if (cur.next.val == cur.next.next.val) {
                int val = cur.next.val;
                // 这里用while,因为相同的元素都需要被剔除
                while(cur.next != null && cur.next.val == val) {
                    cur.next = cur.next.next;
                }
            } else {
                // 指针前移
                cur = cur.next;
            }
        }
        return result.next;
    }
}

翻转/旋转链表

剑指offer 24.翻转链表


单向链表的翻转。代码如下。注意方法一和方法二的区别。

方法一:

/**
 * Definition for singly-linked list.
 * public class ListNode {
 *     int val;
 *     ListNode next;
 *     ListNode(int x) { val = x; }
 * }
 */
class Solution {
    public ListNode reverseList(ListNode head) {
        if(head == null) {
            return head;
        }
        ListNode result = new ListNode(0);
        while(head != null) {
            ListNode tmp = head.next;
            ListNode next = result.next;
            result.next = head;
            head.next = next;

            head = tmp;
        }

        return result.next;
    }
}

方法二:

/**
 * 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 reverseList(ListNode head) {
        if(head == null) return null;
        
        ListNode result = new ListNode();
        result.next = head;
        ListNode prev = result;
        // 在完成翻转后,curr仍然等于head
        ListNode curr = prev.next;
        while(curr.next != null) {
            ListNode tmp = prev.next;
            prev.next = curr.next;
            curr.next = curr.next.next;
            prev.next.next = tmp;
        }
        return result.next;
    }
}

LeetCode25.K个一组翻转链表

相当于分段翻转链表。注意,翻转链表后的返回结果,即head需要不断的更新。代码如下:

/**
 * 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 reverseKGroup(ListNode head, int k) {
        if(head == null) return head;

        ListNode result = new ListNode(0);
        result.next = head;
        ListNode prev = result;
        ListNode end = prev.next;
        int i = 0;
        while(true) {
            if(i == k) {
                prev = reverse(prev, end);
                i = 0;
            } else {
                if(end == null) {
                    break;
                }
                end = end.next;
                i++;
            }
        }

        return result.next;

    }

    /**
     *  param: 0 - 1 - 2 - 3 - 4 - 5. prev = 0, end = 3
     *  return: 0 - 2 - 1 - 3 - 4 - 5. curr = 1
     *  (参考上题的方法二)
     */
    private ListNode reverse(ListNode prev, ListNode end) {
        ListNode curr = prev.next;
        while(curr.next != null && curr.next != end) {
            ListNode tmp = prev.next;
            prev.next = curr.next;
            curr.next = curr.next.next;
            prev.next.next = tmp;
        }
        return curr;
    }
}

Leetcode61.旋转链表

注意该题k的取值范围,可能超过链表长度,所以需要取余。对于上图的例子,两种思路。
思路一:

p1p2分别指向1,然后p1先走k步,然后p1p2同时后移,直到p1为null,此时p2指向3,然后另p3等于p2的next节点,并且p2.next=null, 然后p3继续后移,直到p3.next=null,再另p3.next=head,完毕。

代码如下:

/**
 * 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 rotateRight(ListNode head, int k) {
        if(head == null) return null;
        int length = 0;
        ListNode tmp = head;
        while(tmp != null) {
            length++;
            tmp = tmp.next;
        }
        k = k % length;
        if(k == 0) return head;
        int i = 0;
        ListNode p1 = head;
        ListNode p2 = head;
        while(i <= k) {
            p1 = p1.next;
            i++;
        }
        while(p1 != null) {
            p2 = p2.next;
            p1 = p1.next;
        }
        ListNode newHead = p2.next;
        p2.next = null;
        ListNode p3 = newHead;
        while(p3 != null && p3.next != null) {
            p3 = p3.next;
        }
        p3.next = head;

        return newHead;
    }
}

思路二:

再计算长度时,另tmp指向节点5,然后tmp.next=null。取k = length - k % length,另p1=head,然后p1先走k-1步,指向3,然后p1.next=null。完毕。

代码如下:

/**
 * 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 rotateRight(ListNode head, int k) {
        if(head == null) return null;
        int length = 0;
        ListNode tmp = head;
        ListNode lastNode = head;
        while(tmp != null) {
            length++;
            lastNode = tmp;
            tmp = tmp.next;
        }
        // 将尾节点的next指向首节点
        lastNode.next = head;
        k = length - k % length;
        tmp = head;
        while(k > 1) {
            tmp = tmp.next;
            k--;
        }
        ListNode result = tmp.next;
        tmp.next = null;

        return result;
    }
}
posted @ 2022-10-10 01:12  天山琴子  阅读(41)  评论(0)    收藏  举报