【每日三题】链表中的下一个更大节点、奇偶链表

147 阅读4分钟

携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第6天,点击查看活动详情 >>


每日三刷,剑指千题

计划简介:

  • 每日三题,以中等题为主,简单题为辅进行搭配。保证质量题1道,数量题3道。
  • 每日早通勤在LeetCode手机端选题,思考思路,没答案的直接看题解。
  • 每日中午进行编码,时间控制在一小时之内。
  • 下班前半小时进行整理总结,并发布到掘金每日更文活动。

说明:

  • 基于以前的刷题基础,本次计划以中等题为主,大部分中等题都可以拆分为多个简单题,所以数量保证3,质量保证一道中等题即可。
  • 刷题顺序按照先刷链表、二叉树、栈、堆、队列等基本数据结构,再刷递归、二分法、排序、双指针等基础算法,最后是动态规划、贪心、回溯、搜索等复杂算法。
  • 刷题过程中整理相似题型,刷题模板。
  • 目前进度 120/1000

[1019]链表中的下一个更大节点

给定一个长度为 n 的链表 head

对于列表中的每个节点,查找下一个 更大节点 的值。也就是说,对于每个节点,找到它旁边的第一个节点的值,这个节点的值 严格大于 它的值。

返回一个整数数组 answer ,其中 answer[i] 是第 i 个节点( 从1开始 )的下一个更大的节点的值。如果第 i 个节点没有下一个更大的节点,设置 answer[i] = 0

示例 1:

img

输入:head = [2,1,5]
输出:[5,5,0]

解析

如果是数组的话,双重循环肯定是搞定了,不管快慢,链表就需要考虑指针了。快慢指针 or 滑动窗口?

用双指针写了一版,效率不高,但是能过。

看了一下解析里有用单调栈的,有点类似之前的接雨水了,等到栈的专题是再研究。

经过这么多天的研究,链表涉及最多的就是双指针,因为这狗东西天然就带指针。再有就是递归和迭代。还是比较简单的。

明天会再做几道环形链表,这部分内容就可以告一段落了,开始二叉树。

Code

class Solution {
        public int[] nextLargerNodes(ListNode head) {
            int size = 0;
            ListNode start = head;
            while (head != null) {
                size++;
                head = head.next;
            }
            if (size == 1) {
                return new int[]{0};
            }
            int[] ans = new int[size];
            for (int i = 0; i < size - 1; i++) {
                ListNode index = start.next;
                while (index != null && start.val >= index.val) {
                    index = index.next;
                }
                if (index == null) {
                    ans[i] = 0;
                } else {
                    ans[i] = index.val;
                }
                start = start.next;
            }
            return ans;
        }
    }

[328]奇偶链表

给定单链表的头节点 head ,将所有索引为奇数的节点和索引为偶数的节点分别组合在一起,然后返回重新排序的列表。

第一个节点的索引被认为是 奇数第二个节点的索引为 偶数 ,以此类推。

请注意,偶数组和奇数组内部的相对顺序应该与输入时保持一致。

你必须在 O(1) 的额外空间复杂度和 O(n) 的时间复杂度下解决这个问题。

示例 1:

img

输入: head = [1,2,3,4,5]
输出: [1,3,5,2,4]

解析

有点像分割链表,先把奇数位的拼在一个链表后面,偶数位的拼在一个链表后面,最后把这两个链表拼在一起,看下能不能过。

哈哈哈,过了!

Code

class Solution {
    public ListNode oddEvenList(ListNode head) {
        ListNode ji = new ListNode(0);
        ListNode ou = new ListNode(0);
        ListNode ouHead = ou;
        ListNode jiHead = ji;
​
        int flag = 1;
        while (head!=null){
            ListNode temp = head;
            head = head.next;
            if (flag==1){
                ji.next = temp;
                ji = ji.next;
                flag = 0;
            }else {
                ou.next = temp;
                ou = ou.next;
                flag = 1;
            }
            temp.next = null;
        }
        ji.next = ouHead.next;
        return jiHead.next;
    }
}

[面试题 02.03]删除中间节点

若链表中的某个节点,既不是链表头节点,也不是链表尾节点,则称其为该链表的「中间节点」。

假定已知链表的某一个中间节点,请实现一种算法,将该节点从链表中删除。

例如,传入节点 c(位于单向链表 a->b->c->d->e->f 中),将其删除后,剩余链表为 a->b->d->e->f

示例:

输入:节点 5 (位于单向链表 4->5->1->9 中)
输出:不返回任何数据,从链表中删除传入的节点 5,使链表变为 4->1->9

解析

还是删除节点的套路,水题而已。

Code

class Solution {
    public void deleteNode(ListNode node) {
        node.val = node.next.val;
        node.next = node.next.next;
    }
}

\