LeetCode刷题之链表基础

在这里插入图片描述

请添加图片描述

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

请添加图片描述

class Solution {
    public ListNode removeNthFromEnd(ListNode head, int n) {
        ListNode dummy = new ListNode(-1);
        dummy.next = head;
        ListNode slow = dummy,fast = dummy.next;
        while(n  > 0){
            fast = fast.next;
            n--;
        }
        while(fast != null){
            slow = slow.next;
            fast = fast.next;
        }
        slow.next = slow.next.next;
        return dummy.next;
    }
}

21. 合并两个有序链表

请添加图片描述
递归实现:

class Solution {
    //递归法:每次返回较小的节点
    public ListNode mergeTwoLists(ListNode l1, ListNode l2) {
        if(l1 == null) return l2;
        if(l2 == null) return l1;
        if(l1.val < l2.val){
            l1.next = mergeTwoLists(l1.next,l2);
            return l1;
        }else{
            l2.next = mergeTwoLists(l1,l2.next);
            return l2;
        }
    }
}

迭代实现:

class Solution {
    //迭代实现
    public ListNode mergeTwoLists(ListNode l1, ListNode l2) {
        ListNode dummy = new ListNode(-1);
        ListNode cur = dummy;
        while(l1 != null && l2 != null){
            if(l1.val < l2.val){
                cur.next = l1;
                l1 = l1.next;
            }else{
                cur.next = l2;
                l2 = l2.next;
            }
            cur = cur.next;
        }
        cur.next = l1 == null ? l2 : l1;
        return dummy.next;
    }
}

23. 合并K个升序链表

请添加图片描述
方法一:借助优先队列实现

class Solution {

    //1.方法一:借助优先队列
    public ListNode mergeKLists(ListNode[] lists) {
        if(lists.length < 1) return null;
        ListNode dummy = new ListNode(-1);
        ListNode cur = dummy;
        PriorityQueue<ListNode> queue = new PriorityQueue<>((o1,o2) ->{
            return o1.val - o2.val;
        });
        //将每个链表的头节点加入到优先队列中
        for(ListNode node : lists){
            if(node == null) continue;
            queue.add(node);
        }
        //开始从优先队列中取出元素
        while(!queue.isEmpty()){
            //取出链表中头节点最小的节点
            ListNode minHead = queue.poll();
            cur.next = minHead;
            //接着将 minHead 的下一个节点继续添加到 queue中
            if(minHead.next != null) queue.add(minHead.next);
            cur = cur.next; 
        }
        return dummy.next;
    }
}

方法二:分治法,采用合并两个有序链表的思路:

class Solution {

    //方法二:分治法
    public ListNode mergeKLists(ListNode[] lists) {
        if(lists == null || lists.length == 0) return null;
        return mergeKLists(lists,0, lists.length - 1);
    }

    public ListNode mergeKLists(ListNode[] lists,int l, int r){
        if(l >= r){
            return lists[l];
        }
        int mid = (l + r) / 2;
        ListNode l1 = mergeKLists(lists,l,mid);
        ListNode l2 = mergeKLists(lists,mid + 1,r);
        return mergeTwoLists(l1,l2);
    }

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

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

请添加图片描述

递归代码:

class Solution {
    //1.递归    
    public ListNode swapPairs(ListNode head) {
        if(head == null || head.next == null) return head;
        ListNode next = head.next;
        head.next = swapPairs(next.next);
        next.next = head;
        return next;
    }
}

迭代版本:

class Solution {
    //2.迭代
    public ListNode swapPairs(ListNode head) {
        ListNode dummy = new ListNode(-1);
        ListNode cur = head,pre = dummy;
        dummy.next = cur;
        while(cur != null && cur.next != null){
            ListNode next = cur.next;
            pre.next = next;
            cur.next = next.next;
            next.next = cur;
            pre = cur;
            cur = cur.next;
        }
        return dummy.next;
    }
}

25. K 个一组翻转链表

请添加图片描述

方法一:通过Stack来做链表翻转

class Solution {
    /**
        * 方法二:⽤用栈 每k个节点压⼊入栈中 弹出的就是翻转的链表
        * 注意问题:
        * 问题⼀:剩下的链表个数不不够k个
        * 问题⼆:已经反转的链表与剩下的链表连接起来
    */
    public ListNode reverseKGroup(ListNode head, int k) {
        ListNode dummy = new ListNode(-1);
        Stack<ListNode> stack = new Stack<>();
        ListNode p = dummy;
        while(true){
            int count = 0;
            ListNode cur = head;
            while(cur != null && count < k){
                stack.push(cur);
                cur = cur.next;
                count++;
            }
            if(count != k){
                p.next = head;
                break;
            }
            //在把stack中的链表连起来
            while(!stack.isEmpty()){
                p.next = stack.pop();
                p = p.next;
            }
            p.next = cur;
            head = cur;
        }
        return dummy.next;
    }
}

方法二:进阶版本-》不使用额外的控件

翻转链表时候采用尾插法:

 -1 --> 1 --> 2 --> 3 --> 4 --> node
dummy
 pre
 tail
1.找到 tail 节点
 -1 --> 1 --> 2 --> 3 --> 4 --> node     
dummy                    tail  
pre
2.执行尾部插法
    -1 --> 2 --> 3 --> 4 --> 1 --> node (1)
     pre              tail
    -1 --> 3 --> 4 --> 2 --> 1 --> node (1)
    pre         tail  
    -1 --> 4 --> 3 --> 2 --> 1 --> node (1)
     pre  tail
//终止条件: pre.next != tail 说明当前 k 个节点遍历完成
class Solution {
    //找到需要翻转链表的 pre 节点 和 tail 节点,翻转 pre -- > tail 这一部分
    //尾插法:每次将 pre.next 节点插入到 tail 的后面
    public ListNode reverseKGroup(ListNode head, int k) {
        ListNode dummy = new ListNode(-1);
        dummy.next = head;
        ListNode pre = dummy,tail = dummy;
        while(true){
            int count = 0;
            //1.找 tail 节点
            while(count < k && tail != null){
                tail = tail.next;
                count++;
            }
            //2.如果不满足k个,直接结束最后小于 k 个节点的翻转
            if(tail == null) break;
            //3.尾插法翻转链表
            ListNode newPre = pre.next;
            while(pre.next != tail){
                ListNode cur = pre.next;
                pre.next = cur.next;
                cur.next = tail.next;
                tail.next = cur;
            }
            pre = newPre;
            tail = newPre;
        }
        return dummy.next;
    }
}

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

请添加图片描述

递归代码:

class Solution {
    //递归版本
    public ListNode deleteDuplicates(ListNode head) {
        if(head == null || head.next == null) return head;
        head.next = deleteDuplicates(head.next);
        //如果head和next相等,直接返回head的next节点
        return head.val == head.next.val ? head.next : head;
    }
}

迭代版本:

class Solution {
    //迭代版本
    public ListNode deleteDuplicates(ListNode head) {
        ListNode dummy = new ListNode(-1);
        dummy.next = head;
        while(head != null && head.next != null){
            if(head.val == head.next.val){
                head.next = head.next.next;
            }else{
                head = head.next;
            }
        }
        return dummy.next;
    }
}

160. 相交链表

请添加图片描述
方法:

public class Solution {
    public ListNode getIntersectionNode(ListNode headA, ListNode headB) {
        ListNode p1 = headA,p2 = headB;
        while(p1 != p2){
            p1 = p1 == null ? headB : p1.next;
            p2 = p2 == null ? headA : p2.next;
        }    
        return p1;
    }
}

206. 反转链表

请添加图片描述

递归版本:

class Solution {
    //递归版本
    public ListNode reverseList(ListNode head) {
        if(head == null || head.next == null) return head;
        ListNode tail = reverseList(head.next);
        head.next.next = head;
        head.next = null;
        return tail;
    }
}

迭代版本:

class Solution {
    //迭代版本
    public ListNode reverseList(ListNode head) {
        ListNode dummy = new ListNode(-1);
        dummy.next = head;
        ListNode pre = head;
        while(head != null && head.next != null){
            ListNode next = head.next;
            pre.next = next.next;
            next.next = dummy.next;
            dummy.next = next;
        }
        return dummy.next;
    }
}


class Solution {
    //迭代,头插入法
    public ListNode reverseList(ListNode head) {
        ListNode dummy = new ListNode(-1);
        while(head != null){
            ListNode next = head.next;
            head.next = dummy.next;
            dummy.next = head;
            head = next;
        }
        return dummy.next;
    }
}

445. 两数相加 II

请添加图片描述

方法:借助栈实现倒序相加

class Solution {

    //借助栈实现倒序相加,需要注意进位 问题
    public ListNode addTwoNumbers(ListNode l1, ListNode l2) {
        Stack<ListNode> stack1 = buildStack(l1);
        Stack<ListNode> stack2 = buildStack(l2);
        int ca = 0;
        ListNode dummy = new ListNode(-1);
        while(!stack1.isEmpty() || !stack2.isEmpty() || ca != 0){
            int a = stack1.isEmpty() ? 0 : stack1.pop().val;
            int b = stack2.isEmpty() ? 0 : stack2.pop().val;
            int sum = a + b + ca;
            ListNode node = new ListNode(sum % 10);
            node.next = dummy.next;
            dummy.next = node;
            ca = sum / 10;
        }
        return dummy.next;
    }

    public Stack<ListNode> buildStack(ListNode head){
        Stack<ListNode> stack = new Stack<>();
        while(head != null){
            stack.add(head);
            head = head.next;
        }
        return stack;
    }
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值