链表13题

参考文献 https://chienmy.gitbook.io/algorithm-pattern-java/shu-ju-jie-gou/linked_list

83 删除排序链表中重复元素

/**
 * 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) return null; // 注意考虑空指针输入情况
        ListNode left  = head;
        ListNode right = head.next;
        while(right!=null){
            if(left.val==right.val){
                right = right.next;
                left.next = right;
            }else{
                left = left.next;
                right = right.next;
            }
        }

        return head;
    }
}

82 删除排序链表中的重复元素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) return null;
        if(head.next==null) return head;
        

        ListNode dummynode = new ListNode(-1,head);
        ListNode left = dummynode;
        ListNode right = head;

        while(right!=null && right.next!=null){
            if(left.next.val == right.next.val){ 
                if(right.next.next==null){
                    left.next = null;break; // 链表只有两个重复结点,删除后跳出循环
                }
                if(right.next.val == right.next.next.val){ // 删除奇数个重复结点
                    left.next.next = right.next.next;
                }else{ // 删除偶数个
                    left.next = right.next.next;
                    right = left.next;
                }
            }else{
                left = left.next;
                right = right.next;
            }
        }

        return dummynode.next;
    }
}

206 反转链表

递归

/**
 * 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;
        if(head.next==null) return head;

        ListNode revlist = reverseList(head.next);
        head.next.next = head;
        head.next = null;
        return revlist;
    }
}

迭代

/**
 * 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 pre = null;
        ListNode cur = head;

        while(cur!=null){
            ListNode tmp = cur.next;
            cur.next = pre;
            pre = cur;
            cur = tmp;
        }
        return pre;
    }
}

92 反转链表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 reverseBetween(ListNode head, int left, int right) {
        if(head==null) return null;

        ListNode dummynode = new ListNode(-1,head);
        ListNode front = dummynode;
        for(int i=0;i<left-1;i++){
            front = front.next;
        }

        ListNode pre,tail,cur;
        pre = tail = front.next;
        cur = pre.next;

        for(int i= 0;i<(right-left);i++){
            ListNode tmp = cur.next;
            cur.next = pre;
            pre = cur;
            cur = tmp;
        }

        front.next = pre;
        tail.next = cur;

        return dummynode.next;
    }
}

21 合并两个有序链表

递归

/**
 * 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 mergeTwoLists(ListNode l1, ListNode l2) {
        if(l1==null || l2==null) return l1==null ? l2 : l1; 
        if(l1.val <= l2.val){
            l1.next = mergeTwoLists(l1.next,l2);
        }else{
            l2.next = mergeTwoLists(l2.next,l1);
        }
        return l1.val <= l2.val ? l1 : l2;
    }
}

23 合并K个升序链表

/**
 * 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 mergeKLists(ListNode[] lists) {
        return merge(lists,0,lists.length - 1); // 分治,两个两个链表处理
    }

    public ListNode merge(ListNode[] lists,int begin,int end){
        if(begin==end) return lists[begin]; // 说明只有一个链表元素
        if(begin>end) return null; // 不存在
        int mid = (begin+end) >> 1; // 有符号右移一位 0001;相当于平均值向下取整
        return mergeTwoLists( merge(lists,begin,mid) , merge(lists,mid+1,end) ); // 递归不断细分数组,让两个链表合并
    }

    public ListNode mergeTwoLists(ListNode l1, ListNode l2) {
        if(l1==null || l2==null) return l1==null ? l2 : l1; 
        if(l1.val <= l2.val){
            l1.next = mergeTwoLists(l1.next,l2);
        }else{
            l2.next = mergeTwoLists(l2.next,l1);
        }
        return l1.val <= l2.val ? l1 : l2;
    }
}

876 链表的中间结点

快慢指针

/**
 * Definition for singly-linked list.
 * public class ListNode {
 *     int val;
 *     ListNode next;
 *     ListNode(int x) { val = x; }
 * }
 */
class Solution {
    public ListNode middleNode(ListNode head) {
        ListNode slow,fast;
        slow = fast = head;
        while(fast!=null && fast.next!=null){
            slow = slow.next;
            fast = fast.next.next;
        }
        return slow;
    }
}

143 重排链表

先找中间结点分成两个链表,将mid后面的链表反转后拼接两个链表

/**
 * 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 void reorderList(ListNode head) {
        ListNode midnode = middleNode(head);
        ListNode right = midnode.next;
        midnode.next = null;

        ListNode rev = reverseList(right);
        merge(head,rev);
    }

    public ListNode middleNode(ListNode head) {
        ListNode slow,fast;
        slow = fast = head;
        while(fast!=null && fast.next!=null){
            slow = slow.next;
            fast = fast.next.next;
        }
        return slow;
    }

    public ListNode reverseList(ListNode head) {
        if(head==null) return null;
        
        ListNode pre = null;
        ListNode cur = head;

        while(cur!=null){
            ListNode tmp = cur.next;
            cur.next = pre;
            pre = cur;
            cur = tmp;
        }
        return pre;
    }

    public void merge(ListNode l1,ListNode l2){
        ListNode l1_tmp;
        ListNode l2_tmp;
        while(l1!=null && l2!=null){
            l1_tmp = l1.next;
            l2_tmp = l2.next;

            l1.next = l2;
            l1 = l1_tmp;

            l2.next = l1;
            l2 = l2_tmp;
        }
    }
}

234 回文链表

快慢指针、反转链表

/**
 * 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 boolean isPalindrome(ListNode head) {
        ListNode slow,fast,pre,tmp,rev;
        slow = fast = head;
        rev = pre = null;
        
        // 查找中间结点的同时反转前半部分链表
        while(fast!=null && fast.next!=null){
            fast = fast.next.next;

            tmp = slow.next;
            slow.next = pre;
            pre = slow;
            slow = tmp;
        }

        if(fast!=null){ // 奇数链表
            rev = slow.next;
        }else{ // 偶数链表
            rev = slow;
        }
        // 比较两部分链表
        while(rev!=null){
            if(rev.val != pre.val) return false;
            rev = rev.next;
            pre = pre.next;
        }
        return true;
    }
}

141 环形链表

快慢指针,快慢指针相同则有环,如果有环每走一步快慢指针距离会减 1

/**
 * 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 || head.next==null) return false;

        ListNode slow,fast;
        slow = fast = head;
        while(fast!=null){
            fast = fast.next;
            if(fast!=null){
                fast = fast.next;
            }
            if(slow == fast) return true;
            slow = slow.next;
        }
        return false;
    }
}

142 环形链表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) {
        if(head==null || head.next==null) return null;
        ListNode slow ,fast;
        slow = fast = head;
        while(fast!=null && fast.next!=null){
            fast = fast.next.next;
            slow = slow.next;
            if(fast == slow){
                slow = head;
                while(fast!=slow){
                    slow = slow.next;
                    fast = fast.next;
                }
                return fast;
            }
        }

        return null;
    }
}

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

快慢指针,虚拟头结点;
先让fast走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) {
        ListNode dummynode = new ListNode(-1,head);
        ListNode slow , fast;
        slow = fast = dummynode;

        for(int i=0;i<n;i++){
            fast = fast.next;
        }

        while(fast.next!=null){
            fast = fast.next;
            slow = slow.next;
        }

        slow.next = slow.next.next;

        return dummynode.next;
    }
}

138 复制带随机指针的链表

复制节点跟在原节点后面

/*
// Definition for a Node.
class Node {
    int val;
    Node next;
    Node random;

    public Node(int val) {
        this.val = val;
        this.next = null;
        this.random = null;
    }
}
*/

class Solution {
    public Node copyRandomList(Node head) {
        if(head == null) return null;

        // 在每一原结点后克隆一个没有random的结点
        Node cur = head;
        while(cur!=null){
            Node cloneNode = new Node(cur.val);
            cloneNode.next = cur.next;

            Node tmp = cur.next;
            cur.next = cloneNode;
            cur = tmp;
        }

        // 为克隆的结点根据原结点的random找其对应的random,根据原结点后跟着其克隆结点的特点操作
        cur = head;
        while(cur != null){
            if(cur.random != null){ // 跳过random为null的原结点
                cur.next.random = cur.random.next; // 克隆结点的random
            }
            cur = cur.next.next;
        }

        // 分开两条链表,返回克隆链表;
        cur = head;
        Node cloneHead = head.next;
        while(cur != null && cur.next != null){
            Node tmp = cur.next;
            cur.next = cur.next.next;
            cur = tmp;
        }
        return cloneHead;
    }
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值