0
点赞
收藏
分享

微信扫一扫

【牛客网面试必刷TOP101】链表篇(一)

北冥有一鲲 2023-05-16 阅读 82

【牛客网面试必刷TOP101】链表篇(一)

前言

刷题网站

牛客网:https://www.nowcoder.com/activity/oj
在这里插入图片描述

刷题!

BM1 反转链表

https://www.nowcoder.com/share/jump/6243324481684200142743
在这里插入图片描述

思路一:用栈解决

链表的反转是老生常谈的一个问题了,同时也是面试中常考的一道题。最简单的一种方式就是使用栈,因为栈是先进后出的。实现原理就是把链表节点一个个入栈,当全部入栈完之后再一个个出栈,出栈的时候在把出栈的结点串成一个新的链表。原理如下:
在这里插入图片描述
在这里插入图片描述

public class Solution {
        public ListNode ReverseList(ListNode head) {
            Stack<ListNode> stack= new Stack<>();
            //把链表节点全部摘掉放到栈中
            while (head != null) {
                stack.push(head);
                head = head.next;
            }
            if (stack.isEmpty())
                return null;
            ListNode node = stack.pop();
            ListNode dummy = node;
            //栈中的结点全部出栈,然后重新连成一个新的链表
            while (!stack.isEmpty()) {
                ListNode tempNode = stack.pop();
                node.next = tempNode;
                node = node.next;
            }
            //最后一个结点就是反转前的头结点,一定要让他的next
            //等于空,否则会构成环
            node.next = null;
            return dummy;
        }
    }

思路二:双链表求解

双链表求解是把原链表的结点一个个摘掉,每次摘掉的链表都让他成为新的链表的头结点,然后更新新链表。
在这里插入图片描述

public ListNode ReverseList(ListNode head) {
        ListNode newhead=null;
        while(head!=null){
            ListNode tmp=head.next;
            head.next=newhead;
            newhead=head;
            head=tmp;
        }
        return newhead;
    }

思路三:递归解决

public ListNode ReverseList(ListNode head) {
        if(head==null||head.next==null){
            return head;
        }
        ListNode next=head.next;
        ListNode reverse=ReverseList(next);
        next.next=head;
        head.next=null;
        return reverse;
    }

总结

在这里插入图片描述

BM2 链表内指定区间反转

https://www.nowcoder.com/share/jump/6243324481684200129562
在这里插入图片描述

思路一:头插法迭代

思路大体可以分为三个步骤:

public ListNode reverseBetween (ListNode head, int m, int n) {
        ListNode res=new ListNode(-1);
        res.next=head;
        ListNode pre=res;
        ListNode cur=head;
        for(int i=1;i<m;i++){
            pre=cur;
            cur=cur.next;
        }
        for(int i=m;i<n;i++){
            ListNode tmp=cur.next;
            cur.next=tmp.next;
            tmp.next=pre.next;
            pre.next=tmp;
        }
        return res.next;
    }

思路二:递归

我们来看看另一种分析:如果m == 1,就相当于反转链表的前n个元素;如果 m != 1,我们把 head 的索引视为 1,那么我们是想从第 m 个元素开始反转,如果把 head->next 的索引视为1,那相对于 head->next的反转的区间应该是从第 m−1个元素开始的,以此类推,反转区间的起点往后就是一个子问题。
在这里插入图片描述

 ListNode temp = null;
    public ListNode reverse(ListNode head, int n){
        //只颠倒第一个节点,后续不管
        if(n == 1){
            temp = head.next;
            return head;
        }
        //进入子问题
        ListNode node = reverse(head.next, n - 1);
        //反转
        head.next.next = head;
        //每个子问题反转后的尾拼接第n个位置后的节点
        head.next = temp;
        return node;
    }
    public ListNode reverseBetween (ListNode head, int m, int n) {
        //从第一个节点开始
        if(m == 1)
            return reverse(head, n);
        //缩减子问题
        ListNode node = reverseBetween(head.next, m - 1, n - 1);
        //拼接已翻转
        head.next = node;
        return head;
    }

BM3 链表中的节点每k个一组翻转

https://www.nowcoder.com/share/jump/6243324481684200097423
在这里插入图片描述

思路:递归

public ListNode reverseKGroup (ListNode head, int k) {
        ListNode tail=head;
        for(int i=0;i<k;i++){
            if(tail==null){
                return head;
            }
            tail=tail.next;
        }
        ListNode pre=null;
        ListNode cur=head;
        while(cur!=tail){
            //翻转
            ListNode temp = cur.next;
            cur.next = pre;
            pre = cur;
            cur = temp;
        }
        head.next=reverseKGroup(tail,k);
        return pre;
    }

总结

链表的题目一定要画图,思路可以从头插法,递归角度思考!

💓 感谢阅读

举报

相关推荐

0 条评论