【算法】单调栈题单(矩阵系列、字典序最小、贡献法)⭐

这篇具有很好参考价值的文章主要介绍了【算法】单调栈题单(矩阵系列、字典序最小、贡献法)⭐。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

题单来源

https://leetcode.cn/problems/beautiful-towers-ii/solutions/2456562/qian-hou-zhui-fen-jie-dan-diao-zhan-pyth-1exe/

经典题单

496. 下一个更大元素 I(单调栈模板题)

https://leetcode.cn/problems/next-greater-element-i/description/
【算法】单调栈题单(矩阵系列、字典序最小、贡献法)⭐,算法刷题记录,算法,矩阵,单调栈,力扣,leetcode,贡献法,贪心
提示:

1 <= nums1.length <= nums2.length <= 1000
0 <= nums1[i], nums2[i] <= 10^4
nums1和nums2中所有整数 互不相同
nums1 中的所有整数同样出现在 nums2 中

进阶:你可以设计一个时间复杂度为 O(nums1.length + nums2.length) 的解决方案吗?

预先处理出 nums2 数组中每个数字的下一个更大数字,存储在哈希表中。
生成 ans 数组时,从哈希表中逐个取结果即可。

class Solution {
    public int[] nextGreaterElement(int[] nums1, int[] nums2) {
        int n = nums1.length;
        Map<Integer, Integer> m = new HashMap<>();
        Deque<Integer> stk = new ArrayDeque<>();
        for (int i = 0; i < nums2.length; ++i) {
            while (!stk.isEmpty() && nums2[i] > stk.peek()) m.put(stk.pop(), nums2[i]);
            stk.push(nums2[i]);
        }
        int[] ans = new int[n];
        for (int i = 0; i < n; ++i) {
            ans[i] = m.getOrDefault(nums1[i], -1);
        }
        return ans;
    }
}

503. 下一个更大元素 II(单调栈+循环数组)

https://leetcode.cn/problems/next-greater-element-ii/description/

【算法】单调栈题单(矩阵系列、字典序最小、贡献法)⭐,算法刷题记录,算法,矩阵,单调栈,力扣,leetcode,贡献法,贪心

class Solution {
    public int[] nextGreaterElements(int[] nums) {
        int n = nums.length;
        int[] ans = new int[n];
        Arrays.fill(ans, -1);
        Deque<Integer> stk = new ArrayDeque<>();
        for (int i = 0; i < 2 * n - 1; ++i) {
            int id = i % n;
            while (!stk.isEmpty() && nums[id] > nums[stk.peek()]) ans[stk.pop()] = nums[id];
            stk.push(id);
        }
        return ans;
    }
}

2454. 下一个更大元素 IV(第二个更大的元素:两个单调栈)

https://leetcode.cn/problems/next-greater-element-iv/description/
【算法】单调栈题单(矩阵系列、字典序最小、贡献法)⭐,算法刷题记录,算法,矩阵,单调栈,力扣,leetcode,贡献法,贪心

提示:
1 <= nums.length <= 10^5
0 <= nums[i] <= 10^9

用两个单调栈来分别处理第一个和第二个更大,当第一次被弹出时,说明遇到了第一个更大的元素,将其弹出后放入第二个单调栈中。

在第二个单调栈被弹出的元素说明遇到了第二个更大的元素。

class Solution {
    public int[] secondGreaterElement(int[] nums) {
        int n= nums.length;
        int[] ans = new int[n];
        Arrays.fill(ans, -1);
        Deque<Integer> stk = new ArrayDeque<>(), stk2 = new ArrayDeque<>();
        for (int i = 0; i < n; ++i) {
            // 处理第二个单调栈
            while (!stk2.isEmpty() && nums[i] > nums[stk2.peek()]) {
                ans[stk2.pop()] = nums[i];
            }
            // 处理第一个单调栈
            List<Integer> ls = new ArrayList<>();
            while (!stk.isEmpty() && nums[i] > nums[stk.peek()]) {
                ls.add(stk.pop());
            }
            for (int j = ls.size() - 1; j >= 0; --j) stk2.push(ls.get(j));
            stk.push(i);
        }
        return ans;
    }
}

456. 132 模式(单调栈找上一个更大元素+哈希表记录最小值)

https://leetcode.cn/problems/132-pattern/description/

【算法】单调栈题单(矩阵系列、字典序最小、贡献法)⭐,算法刷题记录,算法,矩阵,单调栈,力扣,leetcode,贡献法,贪心

枚举的x作为最后一个数字,当找到上一个更大的数字时,考虑其之前出现的最小值是否小于当前值即可。

class Solution {
    public boolean find132pattern(int[] nums) {
        // 找上一个更大元素,并检查当前是否大于更大元素之前出现过的最小值
        int mn = Integer.MAX_VALUE;     // 记录已经枚举过的数值中的最小值
        Deque<Integer> stk = new ArrayDeque<>();
        Map<Integer, Integer> m = new HashMap<>();  // 记录各个数值之前出现的最小值
        for (int x: nums) {
            m.put(x, mn);
            while (!stk.isEmpty() && x >= stk.peek()) {
                stk.pop();
            }
            if (!stk.isEmpty() && x > m.get(stk.peek())) return true;
            stk.push(x);
            if (x < mn) mn = x;
        }
        return false;
    }
}

739. 每日温度

https://leetcode.cn/problems/daily-temperatures/description/

【算法】单调栈题单(矩阵系列、字典序最小、贡献法)⭐,算法刷题记录,算法,矩阵,单调栈,力扣,leetcode,贡献法,贪心

class Solution {
    public int[] dailyTemperatures(int[] temperatures) {
        int n = temperatures.length;
        int[] ans = new int[n];
        Deque<Integer> stk = new ArrayDeque<>();
        for (int i = 0; i < n; ++i) {
            // 维护单调递减的单调栈
            while (!stk.isEmpty() && temperatures[i] > temperatures[stk.peek()]) {
                // 当元素被弹出时,说明遇到了更大的值
                ans[stk.peek()] = i - stk.pop();
            }
            stk.push(i);
        }
        return ans;
    }
}

901. 股票价格跨度

https://leetcode.cn/problems/online-stock-span/description/
【算法】单调栈题单(矩阵系列、字典序最小、贡献法)⭐,算法刷题记录,算法,矩阵,单调栈,力扣,leetcode,贡献法,贪心
提示:
1 <= price <= 10^5
最多调用 next 方法 10^4 次

class StockSpanner {
    int t = 0;
    // 单调递减的单调栈
    Deque<Integer> stk = new ArrayDeque<>();
    List<Integer> ls = new ArrayList<>();

    public StockSpanner() {
        stk.push(-1);
    }
    
    public int next(int price) {    
        ls.add(price);
        while (stk.size() > 1 && price >= ls.get(stk.peek())) {
            stk.pop();
        }
        int res = t - stk.peek();
        stk.push(t++);
        return res;
    }
}

/**
 * Your StockSpanner object will be instantiated and called as such:
 * StockSpanner obj = new StockSpanner();
 * int param_1 = obj.next(price);
 */

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

https://leetcode.cn/problems/next-greater-node-in-linked-list/description/
【算法】单调栈题单(矩阵系列、字典序最小、贡献法)⭐,算法刷题记录,算法,矩阵,单调栈,力扣,leetcode,贡献法,贪心

提示:

链表中节点数为 n
1 <= n <= 10^4
1 <= Node.val <= 10^9

存储列表后,再使用单调栈处理。

class Solution {
    public int[] nextLargerNodes(ListNode head) {
        List<Integer> ls = new ArrayList<>();
        while (head != null) {
            ls.add(head.val);
            head = head.next;
        }
        int n = ls.size();
        int[] ans = new int[n];
        Deque<Integer> stk = new ArrayDeque<>();
        for (int i = 0; i < n; ++i) {
            while (!stk.isEmpty() && ls.get(i) > ls.get(stk.peek())) {
                ans[stk.pop()] = ls.get(i);
            }
            stk.push(i);
        }
        return ans;
    }
}

1124. 表现良好的最长时间段(单调栈解法⭐⭐⭐⭐⭐)

https://leetcode.cn/problems/longest-well-performing-interval/description/
【算法】单调栈题单(矩阵系列、字典序最小、贡献法)⭐,算法刷题记录,算法,矩阵,单调栈,力扣,leetcode,贡献法,贪心
提示:
1 <= hours.length <= 10^4
0 <= hours[i] <= 16

先正序遍历用单调栈处理,再反向遍历利用单调栈中结果。

class Solution {
    public int longestWPI(int[] hours) {
        int n = hours.length;
        int[] s = new int[n + 1];
        ArrayDeque<Integer> stk = new ArrayDeque<>();
        stk.push(0);
        // 单调递减的单调栈
        for (int i = 1; i <= n; ++i) {
            s[i] = s[i - 1] + (hours[i - 1] > 8? 1: -1);
            if (s[i] < s[stk.peek()]) stk.push(i);
        }
        int ans = 0;
        for (int i = n; i > 0; --i) {
            while (!stk.isEmpty() && s[i] > s[stk.peek()]) {
                ans = Math.max(ans, i - stk.pop());
            }
        }
        return ans;
    }
}

1475. 商品折扣后的最终价格(单调栈找下一个更小的元素)

https://leetcode.cn/problems/final-prices-with-a-special-discount-in-a-shop/description/
【算法】单调栈题单(矩阵系列、字典序最小、贡献法)⭐,算法刷题记录,算法,矩阵,单调栈,力扣,leetcode,贡献法,贪心

提示:
1 <= prices.length <= 500
1 <= prices[i] <= 10^3

class Solution {
    public int[] finalPrices(int[] prices) {
        int n = prices.length;
        // 单调栈找下一个<=的元素
        Deque<Integer> stk = new ArrayDeque<>();
        for (int i = 0; i < n; ++i) {
            while (!stk.isEmpty() && prices[i] <= prices[stk.peek()]) {
                prices[stk.pop()] -= prices[i];
            }
            stk.push(i);
        }
        return prices;
    }
}

2289. 使数组按非递减顺序排列⭐⭐⭐⭐⭐

https://leetcode.cn/problems/steps-to-make-array-non-decreasing/description/

【算法】单调栈题单(矩阵系列、字典序最小、贡献法)⭐,算法刷题记录,算法,矩阵,单调栈,力扣,leetcode,贡献法,贪心

提示:
1 <= nums.length <= 10^5
1 <= nums[i] <= 10^9

解法——等价转换 + 利用单调性🐂

https://leetcode.cn/problems/steps-to-make-array-non-decreasing/solutions/1524614/by-endlesscheng-s2yc/
【算法】单调栈题单(矩阵系列、字典序最小、贡献法)⭐,算法刷题记录,算法,矩阵,单调栈,力扣,leetcode,贡献法,贪心

class Solution {
    public int totalSteps(int[] nums) {
        int n = nums.length;
        // 单调递减 存储元素及其被删除的时刻
        Deque<int[]> stk = new ArrayDeque<>();
        int ans = 0;
        for (int i = 0; i < n; ++i) {
            int maxT = 0;
            while (!stk.isEmpty() && nums[i] >= nums[stk.peek()[0]]) {
                maxT = Math.max(stk.pop()[1], maxT);
            }
            if (!stk.isEmpty()) ans = Math.max(ans, maxT + 1);
            stk.push(new int[]{i, maxT + 1});
        }
        return ans;
    }
}

矩形系列

见:【算法】单调栈题单——矩阵系列

字典序最小

见:【算法】单调栈题单——字典序最小

贡献法

2818. 操作使得分最大(⭐质因数分解+单调栈贡献法+排序贪心)好题!

https://leetcode.cn/problems/apply-operations-to-maximize-score/

【算法】单调栈题单(矩阵系列、字典序最小、贡献法)⭐,算法刷题记录,算法,矩阵,单调栈,力扣,leetcode,贡献法,贪心
提示:
1 <= nums.length == n <= 10^5
1 <= nums[i] <= 10^5
1 <= k <= min(n * (n + 1) / 2, 10^9)

出自周赛:【力扣周赛】第 358 场周赛(大杂烩题目:质因数分解+快速幂+单调栈+贡献法)

class Solution {
    final long MOD = (long)1e9 + 7;
    final static int MX = (int)1e5 + 1;

    static int[] omega = new int[MX];
    static {
        for (int i = 2; i < MX; ++i) {
            if (omega[i] == 0) {    // i 是质数
                for (int j = i; j < MX; j += i) {
                    omega[j]++;     // i 是 j 的一个质因子
                }
            }
        }
    }
    
    public int maximumScore(List<Integer> nums, int k) {
        int n = nums.size();
        int[][] scores = new int[n][2];
        for (int i = 0; i < n; ++i) {
            scores[i][0] = op(nums.get(i));         // 求质数分数
        }
        Deque<Integer> stk = new ArrayDeque<>();
        int[] l = new int[n], r = new int[n];       // 存储各个元素对应可以选择的l~r范围
        Arrays.fill(l, -1);
        Arrays.fill(r, n);
        
        for (int i = 0; i < n; ++i) {
            while (!stk.isEmpty() && scores[i][0] > scores[stk.peek()][0]) {
                r[stk.pop()] = i;
            }
            if (!stk.isEmpty()) l[i] = stk.peek();
            stk.push(i);
        }
        for (int i = 0; i < n; ++i) {
            scores[i][0] = nums.get(i);             // 元素的贡献
            scores[i][1] = (r[i] - i) * (i - l[i]); // 元素可以被选择的次数
        }
        
        // 排序+贪心找 k次操作对应哪些元素
        Arrays.sort(scores, (x, y) -> y[0] - x[0]);     // 分数倒序排序
        long ans = 1;
        for (int i = 0; i < n && k > 0; ++i) {
            if (scores[i][1] <= k) {
                ans = (ans * qmi((long)scores[i][0], (long)scores[i][1])) % MOD;
            } else {
                ans = (ans * qmi((long)scores[i][0], (long)k)) % MOD;
                break;
            }
            k -= scores[i][1];
        }
        return (int)ans;
    }
    
    // 质因数分解 得到不同质因数的数量
    public int op(int x) {
        return omega[x];
    }
    
    // 快速幂
    public long qmi(long a, long b) {
        long p = MOD;
        long res = 1 % p, t = a;
        while (b != 0) {
            if ((b & 1) == 1) res = res * t % p;
            t = t * t % p;
            b >>= 1;
        }
        return res;
    }
}

更多题目

更多见:【算法】贡献法相关题目练习文章来源地址https://www.toymoban.com/news/detail-773228.html

到了这里,关于【算法】单调栈题单(矩阵系列、字典序最小、贡献法)⭐的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 算法实验二 矩阵最小路径和 LIS

    leetcode裸题 最小路径和 给定一个包含非负整数的 *m* x *n* 网格 grid ,请找出一条从左上角到右下角的路径,使得路径上的数字总和为最小。 说明: 每次只能向下或者向右移动一步。 示例 1: 示例 2: 提示: m == grid.length n == grid[i].length 1 = m, n = 200 0 = grid[i][j] = 200 完整实现 题

    2024年04月15日
    浏览(28)
  • 【算法设计与分析】求解矩阵最小路径和问题

    《算法设计与分析》的实验,稍微记录一下,欢迎讨论。 给定一个m行n列的矩阵,从左上角开始每次只能向右或者向下移动,最后到达右下角的位置,路径上的所有数字累加起来作为这条路径的路径和。编写一个实验程序求所有路径和中的最小路径和。例如,一下矩阵中的路

    2024年02月08日
    浏览(38)
  • 使用邻接矩阵实现最小生成树Prim算法 题目编号:1135

    用邻接矩阵存储无向图,实现最小生成树Prim算法,图中边的权值为整型,顶点个数少于10个。 部分代码提示: #include using namespace std; const int MaxSize = 10; const int INF = 32767; class MGraph { public: MGraph(char a[], int n, int e); private: char vertex[MaxSize]; int arc[MaxSize][MaxSize]; int vertexNum, arcNum; }

    2024年02月06日
    浏览(39)
  • 算法-有序数组的平方,长度最小的子数组,螺旋矩阵II

    伪装成一个老手! 题目 给你一个按 非递减顺序 排序的整数数组 nums,返回每个数字的平方组成的新数组,要求也按非递减顺序排序。 示例 : 输入:nums = [-4,-1,0,3,10] 输出:[0,1,9,16,100] 解释:平方后,数组变为 [16,1,0,9,100] 排序后,数组变为 [0,1,9,16,100] 来源:力扣977 思路 遍

    2024年02月11日
    浏览(43)
  • C++二分查找算法:有序矩阵中的第 k 个最小数组和

    二分查找算法合集 C++二分查找算法:查找和最小的 K 对数字 十分接近m恒等于2 给你一个 m * n 的矩阵 mat,以及一个整数 k ,矩阵中的每一行都以非递减的顺序排列。 你可以从每一行中选出 1 个元素形成一个数组。返回所有可能数组中的第 k 个 最小 数组和。 示例 1: 输入:

    2024年02月05日
    浏览(50)
  • 算法题目题单+题解——图论

    本文为自己做的一部分图论题目,作为题单列出,持续更新。 题单由题目链接和题解两部分组成,题解部分提供简洁题意,代码仓库:Kaiser-Yang/OJProblems。 对于同一个一级标题下的题目,题目难度尽可能做到递增。 题目链接:Luogu P3547 [POI2013] CEN-Price List 题解: 题目链接:

    2024年02月19日
    浏览(38)
  • 算法训练第二天|977.有序数组的平方、209.长度最小的有序数组、59.螺旋矩阵2

    题目链接:力扣 思路:同样使用双指针的方法,这样就可以只遍历一次原数组。 可以考虑需要按照一个顺序来遍历,那就是从大到小或者从小到大,我选择的是从大到小。 不难看出,原数组将每个数平方后,呈现从两边到中间逐渐减小的规律。 所以使用一个指针指向原数组

    2023年04月22日
    浏览(57)
  • 【算法系列】非线性最小二乘求解-梯度下降法

    ·【算法系列】卡尔曼滤波算法 ·【算法系列】非线性最小二乘求解-直接求解法 ·【算法系列】非线性最小二乘求解-梯度下降法 ·【算法系列】非线性最小二乘-高斯牛顿法  ·【算法系列】非线性最小二乘-列文伯格马夸尔和狗腿算法  文章目录 系列文章 文章目录 前言 一、

    2024年02月16日
    浏览(43)
  • 图的最小生成树算法(图解+代码)| 学不会来看我系列

    在含有n个顶点的连通图中选择n-1条边,构成一棵极小连通子图,并使该连通子图中n-

    2023年04月12日
    浏览(76)
  • 【算法 | 背包专题】分组背包(解题思路+题单)

    上一节,我们提到了什么是01背包,以及如何求解01背包: 【算法 | 背包专题】01背包(状态定义+状态转移+解题流程+题单) 现在,我们来看分组背包。 分组背包问题是背包问题的一种变形。在这个问题中, 物品被分成了若干组 ,每组中的物品相互冲突,也就是说, 每组只

    2024年04月11日
    浏览(38)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包