链表题解

链表

BM1 反转链表

public class Solution {
    // 迭代法:
    public ListNode ReverseList(ListNode head) {
        if(head == null || head.next == null) return head;
        ListNode pre = null, next = head.next;
        while(next != null){
            head.next = pre;
            pre = head;
            head = next;
            next = head.next;
        }
        head.next = pre;
        return head;
    }
    
    // 递归法:
    public ListNode ReverseList(ListNode head) {
        if(head == null || head.next == null) return head;
        ListNode last = ReverseList(head.next);
        head.next.next = head;
        head.next = null;
        return last;
    }

BM2 链表内指定区间反转

public class Solution {
    public ListNode reverseBetween (ListNode head, int m, int n) {
        if(m == 1) return reverseN(head, n);// 反转前n个节点
        // 递归操作
        head.next = reverseBetween(head.next, m - 1, n - 1);
        return head;
    }
    
    // 反转前n个节点
    ListNode successor = null;
    public ListNode reverseN(ListNode head, int n){
        if(n == 1){// 记录successor,一个节点无需反转,直接返回
            successor = head.next;
            return head;
        }
        ListNode last = reverseN(head.next, n - 1);
        head.next.next = head;
        head.next = successor;
        return last;
    }
}

BM3 k个一组反转链表

public class Solution {
    public ListNode reverseKGroup (ListNode head, int k) {
        if(head == null || head.next == null) return head;
        // dumpy虚拟节点,指向头部
        ListNode dumpy = new ListNode(-1);
        dumpy.next = head;
        // end保存每一组k个节点的最后一个节点
        ListNode end = dumpy;
        // 判断该组元素是否够k个,不够则直接退出循环
        for(int i = 0; i < k; i++){
            if(end.next == null) return head;
            end = end.next;
        }
        // 反转前n个节点
        dumpy.next = reverseN(head, k);
        // 对于完成反转节点的组后面的节点,继续k个一组进行反转
        head.next = reverseKGroup(head.next, k);
        return dumpy.next;
    }
    
    // 反转k个节点
    ListNode successor = null;
    public ListNode reverseN(ListNode head, int k){
        if(k == 1){
            successor = head.next;
            return head;
        }
        ListNode last = reverseN(head.next, k - 1);
        head.next.next = head;
        head.next = successor;
        return last;
    }
}

BM4 合并两个排序链表

public class Solution {
    public ListNode Merge(ListNode list1,ListNode list2) {
        if(list1 == null) return list2;
        if(list2 == null) return list1;
        // 创建一个虚拟节点,用于返回
        ListNode dumpy = new ListNode(-1);
        ListNode cur1 = list1, cur2 = list2;
        ListNode cur =dumpy;
        while(cur1 != null && cur2 != null){
            if(cur1.val < cur2.val){
                cur.next = cur1;
                cur1 = cur1.next;
            } else{
                cur.next = cur2;
                cur2 = cur2.next;
            }
            cur = cur.next;
        }
        // 其中一个为null
        cur.next = cur1 == null ? cur2 : cur1;
        return dumpy.next;
    }
}

BM5 合并k个有序链表

import java.util.ArrayList;
import java.util.PriorityQueue;
public class Solution {
    // 采用最小堆处理
    public ListNode mergeKLists(ArrayList<ListNode> lists) {
        // 创建虚拟头结点dumpy(方便返回结果)和cur节点(标记当前节点)
        ListNode dumpy = new ListNode(-1), cur = dumpy;
        // 特殊情况处理
        if(lists.size() == 0) return dumpy.next;
        // 创建一个最小堆优先序列
        PriorityQueue<ListNode> pQueue = new PriorityQueue<ListNode>(lists.size(), (a, b) -> (a.val - b.val));
        // 将每个链表的头结点添加至最小堆中
        for(ListNode head : lists){
            if(head != null) pQueue.add(head);
        }
        // 依次从最小堆中取出堆顶元素,添加至结果链表
        while(!pQueue.isEmpty()){
            ListNode node = pQueue.poll();
            cur.next = node;
            cur = cur.next;
            if(node.next != null) pQueue.add(node.next);
        }
        return dumpy.next;
    }
}

BM6 判断链表是否有环

public class Solution {
    public boolean hasCycle(ListNode head) {
        // 快慢指针
        ListNode fast = head, slow = head;
        while(fast != null && fast.next != null){
            fast = fast.next.next;
            slow = slow.next;
            if(fast == slow) return true;
        }
        return false;
    }
}

BM7 链表中环的入口结点

public class Solution {
    public ListNode EntryNodeOfLoop(ListNode pHead) {
        // 采用快慢指针
        ListNode fast = pHead, slow = pHead;
        while(fast != null && fast.next != null){
            fast = fast.next.next;
            slow = slow.next;
            if(fast == slow){
                slow = pHead;
                while(slow != fast){
                    fast = fast.next;
                    slow = slow.next;
                }
                return slow;
            }
        }
        // 没有坏,返回空节点
        return null;
    }
}

BM8 链表中倒数最后k个节点

public class Solution {
    public ListNode FindKthToTail (ListNode pHead, int k) {
        // 双指针
        ListNode left = pHead, right = pHead;
        for(int i = 0; i < k; i++){
            if(right == null) return null;
            right = right.next;
        }
        while(right != null){
            left = left.next;
            right = right.next;
        }
        return left;
    }
}

BM9 删除链表中的倒数第k个节点

public class Solution {
    public ListNode removeNthFromEnd (ListNode head, int n) {
        // 双指针,先找到待删除节点的前一个节点
        // 虚拟节点dumpy指向头结点的前一个节点,方便返回头节点
        ListNode dumpy = new ListNode(-1);
        dumpy.next = head;
	// left指向dumpy,可以得到待删除节点的前一个节点
        ListNode left = dumpy, right = head;
        for(int i = 0; i < n; i++){
            right = right.next;
        }
        while(right != null){
            left = left.next;
            right = right.next;
        }
        left.next = left.next.next;
        return dumpy.next;
    }
}

BM10 两个链表的第一个公共节点

public class Solution {
    public ListNode FindFirstCommonNode(ListNode pHead1, ListNode pHead2) {
        // 双指针
        // 先判断是否有环
        if(!isCommonNode(pHead1, pHead2)) return null;
        // 有环,则找到第一个公共节点
        ListNode cur1 = pHead1, cur2 = pHead2;
        while(cur1 != cur2){
            cur1 = cur1 == null ? pHead2 : cur1.next;
            cur2 = cur2 == null ? pHead1 : cur2.next;
        }
        return cur1;
    }
    // 判断是否存在环
    public boolean isCommonNode(ListNode pHead1, ListNode pHead2){
        if(pHead1 == null || pHead2 == null) return false;
        // 判断是否有公共节点:通过判断两个链表的最后一个节点是否相同
        while(pHead1.next != null) pHead1 = pHead1.next;
        while(pHead2.next != null) pHead2 = pHead2.next;
        return pHead1.val == pHead2.val;
    }
}

BM11 链表相加(二)

public class Solution {
    public ListNode addInList (ListNode head1, ListNode head2) {
        // 先反转两个链表,然后遍历相加,最后将结果链表反转
        if(head1 == null) return head2;
        if(head2 == null) return head1;
        // 反转两个链表
        head1 = reverseList(head1);
        head2 = reverseList(head2);
        // 虚拟节点dumpy用于返回答案,cur用于指向当前节点
        ListNode dumpy = new ListNode(-1), cur = dumpy;
        // carry纪录进位
        int carry = 0;
        while(head1 != null && head2 != null){
            // 对应位求和
            int sum = head1.val + head2.val + carry;
            carry = sum / 10;
            ListNode node = new ListNode(sum % 10);
            cur.next = node;
            cur = cur.next;
            head1 = head1.next;
            head2 = head2.next;
        }
        // 至少有一个链表为null
        if(head1 == null && head2 == null) {
            if(carry != 0) cur.next = new ListNode(carry);
        }else if(head1 == null){
            ListNode cur2 = head2;
            while(carry != 0 && cur2.next != null) {
                cur2.val += carry;
                carry = cur2.val / 10;
                cur2.val %= 10;
                cur2 = cur2.next;
            }
            if(carry != 0) {// 上面循环结束条件为cur2.next != null
                carry = carry + cur2.val;
                cur2.val = carry >= 10 ? carry % 10 : carry;
                carry /= 10;
            }
            if(carry != 0) cur2.next = new ListNode(carry);
            cur.next = head2;
         }else {
            ListNode cur1 = head1;
            while(carry != 0 && cur1.next != null) {
                cur1.val += carry;
                carry = cur1.val / 10;
                cur1.val %= 10;
                cur1 = cur1.next;
            }
            if(carry != 0) {// 上面循环结束条件为cur2.next != null
                carry = carry + cur1.val;
                cur1.val = carry >= 10 ? carry % 10 : carry;
                carry /= 10;
            }
            if(carry != 0) cur1.next = new ListNode(carry);
            cur.next = head1;
        }
        dumpy = reverseList(dumpy.next);
        return dumpy;
    }
    
    // 反转两个链表
    public ListNode reverseList(ListNode head){
        if(head == null || head.next == null) return head;
        ListNode last = reverseList(head.next);
        head.next.next = head;
        head.next = null;
        return last;
    }
}

BM12 单链表的排序

public class Solution {
    public ListNode sortInList (ListNode head) {
        boolean flag = true;// 标记本次是否有交换
        ListNode cur = head;
        while(flag){
            flag = false;
            while(cur.next != null){
                if(cur.val > cur.next.val){// 无序,则排序
                    swap(cur, cur.next);
                    flag = true;
                }
                cur = cur.next;
            }
            // 遍历到最后一个节点
            cur = head;
        }
        return head;
    }
    // 交换两个节点的值
    public void swap(ListNode node1, ListNode node2){
        int temp = node1.val;
        node1.val = node2.val;
        node2.val = temp;
    }
}

BM13 判断一个链表是否为回文结构

public class Solution {
    public boolean isPail (ListNode head) {
        if(head == null || head.next == null) return true;
        // 快慢指针找到中间位置,反转后半部分,遍历
        ListNode fast = head, slow = head;
        while(fast != null && fast.next != null){
            fast = fast.next.next;
            slow = slow.next;
        }
        // 若只有两个节点,则比较两个元素值是否相等
        if(slow.next == null) return slow.val == head.val;
        // 否则,元素节点超过两个
        slow.next = reverseList(slow.next);
        fast = slow.next;
        slow = head;
        while(fast != null){
            if(fast.val != slow.val) return false;
            fast = fast.next;
            slow = slow.next;
        }
        return true;
    }
    
    // 反转链表,采用迭代方法
    public ListNode reverseList(ListNode head){
        if(head == null || head.next == null) return head;
        ListNode pre = null, next = head.next;
        while(next != null){
            head.next = pre;
            pre = head;
            head = next;
            next = head.next;
        }
        head.next = pre;
        return head;
    }
}

BM14 链表的奇偶重排

public class Solution {
    public ListNode oddEvenList (ListNode head) {
        if(head == null || head.next == null) return head;
        // 将偶数位节点取出构成一个链表,奇数位构成一个链表,然后将两个链表接起来
        ListNode dumpy1 = new ListNode(-1);// 奇数位链表
        ListNode dumpy2 = new ListNode(-1);// 偶数位链表
        dumpy1.next = head;
        dumpy2.next = head.next;
        ListNode cur1 = head, cur2 = head.next;
        // 拆分成两个链表
        while(cur1.next != null && cur2.next != null){
            cur1.next = cur1.next.next;
            cur1 = cur1.next;
            cur2.next = cur2.next.next;
            cur2 = cur2.next;
        }
        // 拼接两个链表
        cur1.next = dumpy2.next;
        return dumpy1.next;
    }
}

BM15 删除有序链表中重复的元素I

public class Solution {
    public ListNode deleteDuplicates (ListNode head) {
        if(head == null || head.next == null) return head;
        ListNode cur = head, next = head.next;
        // cur前面的节点均为不重复的(包括cur)
        while(next != null){
            // 若cur与next相等,则删除next
            if(cur.val == next.val) cur.next = next.next; 
            else cur = cur.next;// 否则,不相等,cur后移
            //next后移
            next = next.next;
        }
        return head;
    }
}

BM16 删除有序链表中重复的元素II

public class Solution {
     public ListNode deleteDuplicates (ListNode head) {
        if(head == null || head.next == null) return head;
        ListNode dumpy = new ListNode(-1);
        dumpy.next = head;
        int num = 0;// 记录cur前面最有后一个重复的数字
        ListNode prev = dumpy, cur = head, next = head.next;
        while(next != null){
            if(cur.val == next.val){// 相等
                num = cur.val;
            } else{ // 不相等
                if(num != cur.val) prev = prev.next;
                prev.next = next;
                cur = next;
            }
            next = next.next;
        }
	// 若cur没有重复过,则添加到结果
        if(num != cur.val) {
             prev.next = cur;
             prev = prev.next;
         }
         prev.next = null;
        return dumpy.next;
    }
}
全部评论

相关推荐

点赞 收藏 评论
分享
牛客网
牛客企业服务