代码随想录-刷题第五十六天

这篇具有很好参考价值的文章主要介绍了代码随想录-刷题第五十六天。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

单调栈理论基础

先介绍单调栈类型的题目,通常是一维数组,要寻找任一个元素的右边或者左边第一个比自己大或者小的元素的位置,此时就要想到可以用单调栈。时间复杂度为O(n)。

单调栈的本质是空间换时间,因为在遍历的过程中需要用一个栈来记录右边第一个比当前元素高的元素,优点是只需要遍历一次。

分析单调栈的时候,我们需要考虑以下几点。

① 单调栈里存放的元素是什么?

单调栈里只需要存放元素的下标i就可以了,如果需要使用对应的元素,直接T[i]就可以获取。

② 单调栈里元素是递增呢?还是递减呢?

这里要根据具体的题目来分析。

使用单调栈主要有三个判断条件。

  • 当前遍历的元素T[i]小于栈顶元素T[st.top()]的情况
  • 当前遍历的元素T[i]等于栈顶元素T[st.top()]的情况
  • 当前遍历的元素T[i]大于栈顶元素T[st.top()]的情况

把这三种情况分析清楚了,也就理解透彻了


739. 每日温度

题目链接:739. 每日温度

思路:借助单调栈来依次遍历数组,具体执行过程可以看代码随想录的分析。

自己再模拟一遍,就会发现:只有单调栈递增(从栈口到栈底顺序),就是求右边第一个比自己大的,单调栈递减的话,就是求右边第一个比自己小的。

class Solution {
    public int[] dailyTemperatures(int[] temperatures) { 
        // 注意,单调栈里加入的元素是下标。
        int[] res = new int[temperatures.length];
        Deque<Integer> stack = new LinkedList<>();
        stack.push(0);
        for (int i = 1; i < temperatures.length; i++) {
            if (temperatures[i] < temperatures[stack.peek()]) {
                // 情况一
                stack.push(i);
            } else if(temperatures[i] == temperatures[stack.peek()]){
                // 情况二
                stack.push(i);
            } else {
                // 情况三
                while (!stack.isEmpty() && temperatures[i] > temperatures[stack.peek()]) {
                    res[stack.peek()] = i - stack.peek();
                    stack.pop();
                }
                stack.push(i);
            }
        }
        return res;
    }
}

496. 下一个更大元素 I

题目链接:496. 下一个更大元素 I

思路:本题相对于上一题增加了条件,难度也有所增加。

注意题目中说是两个没有重复元素 的数组 nums1 和 nums2。可以用map做映射,根据数值快速找到下标,还可以判断nums2[i]是否在nums1中出现过。

遍历nums2,做单调栈处理,找到每一个元素右边最大元素,然后判断是否在nums1中存在,存在的话就要更新结果。

nums2的遍历过程与上一题相同。

class Solution {
    public int[] nextGreaterElement(int[] nums1, int[] nums2) {
        int[] res = new int[nums1.length];
        // 题目说如果不存在对应位置就输出 -1
        Arrays.fill(res, -1);
        // map数组映射nums1,key对应值,val对应下标。
        Map<Integer, Integer> map = new HashMap<>();
        for (int i = 0; i < nums1.length; i++) {
            map.put(nums1[i], i);
        }

        Deque<Integer> stack = new LinkedList<>();
        stack.push(0);

        for (int i = 1; i < nums2.length; i++) {
            if (nums2[i] < nums2[stack.peek()]) {
                // 情况一
                stack.push(i);
            } else if(nums2[i] == nums2[stack.peek()]){
                // 情况二
                stack.push(i);
            } else {
                // 情况三
                while (!stack.isEmpty() && nums2[i] > nums2[stack.peek()]) {
                    if (map.containsKey(nums2[stack.peek()])) {
                        // 该数在nums1中存在,需要更新结果。
                        // 根据map找到nums2[stack.peek()]在nums1中的下标
                        int index = map.get(nums2[stack.peek()]);
                        res[index] = nums2[i];
                    }
                    stack.pop();
                }
                stack.push(i);
            }
        }
        return res;
    }
}

503. 下一个更大元素II

题目链接:503. 下一个更大元素II

思路:本题仍然是利用单调栈来寻找下一个更大数值的问题,只不过数组可以循环来寻找。解决方法是,将两个相同的数组拼接,然后利用单调栈来寻找就好了(寻找过程与每日温度类似)。

class Solution {
    public int[] nextGreaterElements(int[] nums) {
        int[] res = new int[nums.length];
        Arrays.fill(res, -1);
        Deque<Integer> stack = new LinkedList<>();
        stack.push(0);

        // 拼接一个新的nums
        int[] nums2 = new int[nums.length + nums.length];
        for (int i = 0; i < nums.length; i++) {
            nums2[i] = nums[i];
            nums2[i + nums.length] = nums[i];
        }

        for (int i = 1; i < nums2.length; i++) {
            if (nums2[i] <= nums2[stack.peek()]) {
                stack.push(i);
            } else {
                while (!stack.isEmpty() && nums2[i] > nums2[stack.peek()]) {
                    if (stack.peek() < nums.length) {
                        res[stack.peek()] = nums2[i];
                    } else {
                        res[stack.peek() - nums.length] = nums2[i];
                    }
                    stack.pop();
                }
                stack.push(i);
            }
        }
        return res;
    }
}

其实也可以不扩充nums,而是在遍历的过程中模拟走了两遍nums。文章来源地址https://www.toymoban.com/news/detail-798343.html

class Solution {
    public int[] nextGreaterElements(int[] nums) {
        int[] res = new int[nums.length];
        Arrays.fill(res, -1);
        Deque<Integer> stack = new LinkedList<>();
        stack.push(0);
        
        for (int i = 1; i < nums.length * 2; i++) {
            // 模拟遍历两遍nums,注意一下都是用i % nums.length来操作
            if (nums[i % nums.length] <= nums[stack.peek()]) {
                stack.push(i % nums.length);
            } else {
                while (!stack.isEmpty() && nums[i % nums.length] > nums[stack.peek()]) {
                    res[stack.peek()] = nums[i % nums.length];
                    stack.pop();
                }
                stack.push(i % nums.length);
            }
        }
        return res;
    }
}

到了这里,关于代码随想录-刷题第五十六天的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

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

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

相关文章

  • 代码随想录刷题第55天|Leetcode392判断子序列、Leetcode115不同的子序列

    1、Leetcode392判断子序列 题目链接:392判断子序列 本题与1143最长公共子序列 有一点不一样,最长公共子序列求 两个字符串 的最长公共子序列的长度,本题判断s是否为t的子序列。即t的长度是大于等于s的。 1、确定dp数组及下标含义 dp[i][j] 表示以下标i-1为结尾的字符串s,和以

    2024年02月16日
    浏览(10)
  • 代码随想录刷题第6天|哈希表 LeetCode242、LeetCode349、LeetCode202、LeetCode1

    1、LeetCode242 有效的字母异位词 题目链接:242、有效的字母异位词 用哈希表,record[s[i]-\\\'a\\\']++,record[t[i]-\\\'a\\\']--,最后判断record里是否有元素不为0。 2、LeetCode349、两个数组的交集 题目链接:349、两个数组的交集 题目如果没有限制数值的大小,就无法使用数组来做哈希表。如果哈

    2024年02月06日
    浏览(11)
  • 代码随想录刷题第48天|LeetCode198打家劫舍、LeetCode213打家劫舍II、LeetCode337打家劫舍III

    代码随想录刷题第48天|LeetCode198打家劫舍、LeetCode213打家劫舍II、LeetCode337打家劫舍III

    1、LeetCode198打家劫舍 题目链接:198、打家劫舍 1、dp[i]:考虑下标i(包括i)以内的房屋,最多可以偷窃的金额为dp[i] 。 2、递推公式: 如果偷第i房间,那么dp[i] = dp[i - 2] + nums[i] ; 如果不偷第i房间,那么dp[i] = dp[i - 1]; 然后dp[i]取最大值,即dp[i] = max(dp[i - 2] + nums[i], dp[i - 1

    2024年02月08日
    浏览(85)
  • 第10天-代码随想录刷题训练-第五章 栈和队列- ● 理论基础 ● 232.用栈实现队列 ● 225. 用队列实现栈

    第10天-代码随想录刷题训练-第五章 栈和队列- ● 理论基础 ● 232.用栈实现队列 ● 225. 用队列实现栈

    栈和队列对应的三个不同的STL版本,底层实现方式不一样, 为我们所知道的是 SGI STL 栈 栈提供 pop和push等接口, 不提供走访功能 也不提供迭代器, 不像map和set可以使用迭代器遍历,往往不被归类为容器,而是容器适配器 栈的内部实现结构可以使用 verctor、list 和 deque(默认)

    2024年02月04日
    浏览(11)
  • [自我记录]随想录刷题第二天 | 977.有序数组的平方,209.长度最小的子数组,59.螺旋矩阵II

     代码随想录打卡第二天, 新手自我记录一下刷题历程, 仅为自我打卡使用. 今天刷了三道主题, 第一道双指针和第三道模拟做出来了, 第二道写出了暴力解法但是提交leetcode超时了, 测试用例过了18/20, 看了carl哥答案以后自己重新补写了滑动窗口方法. 977. 有序数组的平方 简单题

    2024年02月05日
    浏览(12)
  • 代码随想录第五十天

    题目链接 : 买卖股票的最佳时机 III 自己的思路 :想不到!!!!高维dp数组!! 正确思路 :这里和之前的都不太一样,因为限制了买卖股票的次数,所以我们就加大dp数组的维度;动规五部曲:1、dp数组的含义:dp[i][0]表示一开始不操作的情况、dp[i][1]表示第一次持有(不一定

    2024年02月11日
    浏览(11)
  • 代码随想录刷题

    代码随想录刷题

    704. 二分查找 27. 移除元素

    2024年01月25日
    浏览(13)
  • 【代码随想录】刷题Day47

    198. 打家劫舍 1.dp数组含义:dp[i]为i位置下的最大能得到的价值 2.根据条件:相邻不能偷。i位置的最大价值取决于i-1位置是否已经偷过了。如果偷过了,i位置的最大价值就是dp[i-1],即i位置的物品不偷;如果没有偷过,i位置的最大价值就是dp[i-2]+nuvms[i],i位置的数和对应的d

    2024年02月07日
    浏览(42)
  • 【代码随想录】刷题Day36

    435. 无重叠区间 先从小到大排序,其实本题依然是求出共同区域,只不过题目需要我们删除尽量少的区间。所以我们需要删除的一定是范围跨度大的并且跟其他有公共区间的区域。所以每次更新右边范围都需要考虑最小的范围。 1.if(intervals[i][0]end),说明有重复的区间,那么我

    2024年02月07日
    浏览(41)
  • 【代码随想录】刷题Day31

    【代码随想录】刷题Day31

    455. 分发饼干 贪心的思路就是:小的饼干尽量去匹配胃口小的孩子,这样才能实现尽可能多孩子吃到。 那么代码就很好写了: 1.排序g和s,这样方便查找小的数 2.饼干的位置不停遍历,对应我们需要一个ret代表当前孩子位置 3.如果当前位置为孩子的数量,说明ret记录下所有的

    2024年02月06日
    浏览(41)

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

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

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

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

二维码1

领取红包

二维码2

领红包