Java C++ 算法题解leetcode145商品折扣后最终价格单调栈

目录
  • 题目要求
  • 思路一:暴力模拟
    • Java
    • C++
    • Rust
  • 思路二:单调栈
    • Java
    • C++
    • Rust

题目要求

思路一:暴力模拟

  • 由于数据范围不算离谱,所以直接遍历解决可行。

Java

class Solution {
    public int[] finalPrices(int[] prices) {
        int n = prices.length;
        int[] res = new int[n];
        for (int i = 0; i < n; i++) {
            int discount = 0;
            for (int j = i + 1; j < n && discount == 0; j++) {
                if (prices[j] <= prices[i])
                    discount = prices[j];
            }
            res[i] = prices[i] - discount;
        }
        return res;
    }
}
  • 时间复杂度:O(n^2)
  • 空间复杂度:O(n)

C++

class Solution {
public:
    vector<int> finalPrices(vector<int>& prices) {
        int n = prices.size();
        vector<int> res(n);
        for (int i = 0; i < n; i++) {
            int discount = 0;
            for (int j = i + 1; j < n && discount == 0; j++) {
                if (prices[j] <= prices[i])
                    discount = prices[j];
            }
            res[i] = prices[i] - discount;
        }
        return res;
    }
};
  • 时间复杂度:O(n^2)
  • 空间复杂度:O(n)

Rust

impl Solution {
    pub fn final_prices(prices: Vec<i32>) -> Vec<i32> {
        let n = prices.len();
        let mut res = vec![0;n];
        (0..n).for_each(|i| {
            res[i] = prices[i] - ((i + 1)..n).find(|&j| prices[j] <= prices[i]).map_or(0, |j| prices[j]);
        });
        res
    }
}
  • 遍历存每次的count,最后再遍历计算得出结果
impl Solution {
    pub fn final_prices(prices: Vec<i32>) -> Vec<i32> {
        let n = prices.len();
        let mut discount = vec![0;n];
        for j in 1..n {
            for i in 0..j {
                if discount[i] == 0 && prices[j] <= prices[i] {
                    discount[i] = prices[j];
                }
            }
        }
        prices.iter().zip(discount.iter()).map(|(&x, &y)| x - y).collect::<Vec<i32>>()
    }
}
  • 时间复杂度:O(n^2)
  • 空间复杂度:O(n)

思路二:单调栈

  • 是个逆向思维,不考虑谁是我的折扣,而去考虑我可以是谁的折扣。已知的一个prices[j]只能折扣其左边最近的几个大于它的值,按这个思路分析单调

    • 从前向后依次遍历prices,遇到需要打折的商品,将其下标放入一个容器

      • 若当前处理值小于末尾,那么它就可以作为末尾元素的折扣【因为它是末尾元素后面第一个小于它的值】,将末尾元素取出、折扣、放入已折扣数组(即结果数组),一直重复到容器末尾元素小于当前处理值,则将当前处理值放入容器【为避免该值不可打折造成缺漏,此时将其价格同步至已折扣数组】。
      • 若当前处理的值高于容器内的值,那么它不能作为里面任何一者的折扣,因此直接加入容器。
    • 由此可知,加入容器值会大于容器内的其它值,该容器是单调递增的。此外,处理的一直是容器末尾的元素,添加也是直接补在末尾,所以符合的结构。

Java

class Solution {
    public int[] finalPrices(int[] prices) {
        int n = prices.length;
        int[] res = new int[n]; // 已打折价格
        Deque<Integer> sta = new ArrayDeque<>(); // 待打折下标
        for (int i = 0; i < n; i++) {
            while (!sta.isEmpty() && prices[sta.peekLast()] >= prices[i]) {
                int idx = sta.pollLast();
                res[idx] = prices[idx] - prices[i];
            }
            sta.addLast(i); // 最高
            res[i] = prices[i];
        }
        return res;
    }
}
  • 时间复杂度:O(n)
  • 空间复杂度:O(n)

C++

class Solution {
public:
    vector<int> finalPrices(vector<int>& prices) {
        int n = prices.size();
        vector<int> res(n); // 已打折价格
        stack<int> sta; // 待打折下标
        for (int i = 0; i < n; i++) {
            while (!sta.empty() && prices[sta.top()] >= prices[i]) {
                int idx = sta.top();
                sta.pop();
                res[idx] = prices[idx] - prices[i];
            }
            sta.push(i); // 最高
            res[i] = prices[i];
        }
        return res;
    }
};
  • 时间复杂度:O(n)
  • 空间复杂度:O(n)

Rust

impl Solution {
    pub fn final_prices(prices: Vec<i32>) -> Vec<i32> {
        let n = prices.len();
        let mut res = vec![0;n]; // 已打折价格
        let mut sta = vec![]; // 待打折下标
        for i in 0..n {
            while let Some(&idx) = sta.last() {
                if prices[idx] < prices[i] {
                    break;
                }
                sta.pop();
                res[idx] = prices[idx] - prices[i];
            }
            sta.push(i); // 最高
            res[i] = prices[i];
        }
        res
    }
}
  • 时间复杂度:O(n)
  • 空间复杂度:O(n)

以上就是Java C++ 算法题解leetcode145商品折扣后最终价格单调栈的详细内容,更多关于Java C++ 商品折扣后价格的资料请关注我们其它相关文章!

(0)

相关推荐

  • Java C++ 算法题解leetcode1582二进制矩阵特殊位置

    目录 题目要求 思路:模拟 Java C++ Rust 题目要求 思路:模拟 直接按题意模拟,先算出每行每列中“111”的个数,然后判断统计行列值均为111的位置即可. Java class Solution { public int numSpecial(int[][] mat) { int n = mat.length, m = mat[0].length; int res = 0; int[] row = new int[n], col = new int[m]; for (int i =

  • Java C++题解leetcode消失的两个数字实例

    目录 题目要求 思路:数学推导 Java C++ Rust 总结 题目要求 思路:数学推导 不重复的数组序列可以根据高斯公式计算所有元素的总和: 用当前数组长度加上两个缺失的数字可以得到所有数字长度,即可应用公式. 减去当前数组和即可得到缺失数字和sumsumsum: 两个缺失的数字分别位于m=sum2m=\frac{sum}{2}m=2sum两边: 遍历当前数组中所有小于(或大于)mmm的值,找到缺失的一个: 同样利用两个“和”的差值得到: 利用sumsumsum即可得到另一个. Java c

  • Java C++题解leetcode判定是否为字符重排

    目录 题目要求 思路一:排序 Java C++ Rust 思路二:词频统计 Java C++ Rust 总结 题目要求 思路一:排序 Java class Solution { public boolean CheckPermutation(String s1, String s2) { if(s1.length() != s2.length()) return false; char[] sort1 = s1.toCharArray(); Arrays.sort(sort1); char[]

  • Java C++ 题解leetcode1619删除某些元素后数组均值

    目录 题目要求 思路:模拟 Java C++ Rust 题目要求 思路:模拟 根据题意模拟即可: 排序然后只取中间符合条件的数加和然后计算均值: 根据给出的数组长度n为20的倍数,5%可直接取n/20: 两边各去除5%,则剩余长度为0.9n. Java class Solution { public double trimMean(int[] arr) { Arrays.sort(arr); int n = arr.length, tot = 0; for (int i = n / 20; i

  • Java C++算法题解leetcode1592重新排列单词间的空格

    目录 题目要求 思路:模拟 Java C++ Rust 题目要求 思路:模拟 模拟就完了 统计空格数量和单词数量,计算单词间应有的空格数,将它们依次放入结果字符串,若有余数则在末尾进行填补. Java class Solution { public String reorderSpaces(String text) { int n = text.length(), spcnt = 0; List<String> words = new ArrayList<>(); for (int

  • Java C++题解leetcode672灯泡开关示例

    目录 题目要求 思路:找规律 Java C++ Rust 总结 题目要求 思路:找规律 找到尽可能最精简的通项表达,今日参考:京城打工人 首先,归纳每个开关会影响的灯,其中(k=0,1,2,…): 开关 反转灯编号 一 k 二 2k 三 2k+1 四 3k+1 可见灯以6盏为周期具有相同变化,所以以下只需要推导第一个周期里的6盏灯即可. 观察前6盏灯: 灯 开关 1 一.三.四 2 一.二 3 一.三 4 一.二.四 5 一.三 6 一.二 发现灯2.6和3.5分别受同样的开关影响,所以状态相同

  • Java C++ 算法题解leetcode145商品折扣后最终价格单调栈

    目录 题目要求 思路一:暴力模拟 Java C++ Rust 思路二:单调栈 Java C++ Rust 题目要求 思路一:暴力模拟 由于数据范围不算离谱,所以直接遍历解决可行. Java class Solution { public int[] finalPrices(int[] prices) { int n = prices.length; int[] res = new int[n]; for (int i = 0; i < n; i++) { int discount = 0; fo

  • Java C++ 算法题解leetcode669修剪二叉搜索树示例

    目录 题目要求 思路一:模拟迭代 Java C++ 思路二:递归 Java C++ Rust 题目要求 思路一:模拟迭代 依次判断每个节点是否合法: 首先找出结果的根,若原根小了就拉右边的过来,大了拉左边的过来做新根: 然后分别判断左右子树的大小,由于二叉搜索树的性质,子树只需要判断一边就好: 左子树判断是否>low,合法就向左下走,不合法往右下: 右子树判断是否<high,合法就向右下走,不合法往左下. Java class Solution { public TreeNode trimBS

  • Java C++ 算法题解leetcode1608特殊数组特征值

    目录 题目要求 思路一:枚举 + 二分 Java C++ 思路二:二分枚举 Java C++ 思路三:倒序枚举 Java C++ 题目要求 思路一:枚举 + 二分 逐一枚举值域内的所有值,然后二分判断是否合法. Java class Solution { public int specialArray(int[] nums) { Arrays.sort(nums); int n = nums.length; for (int x = 0; x <= nums[n - 1]; x++) { //

  • Java C++算法题解leetcode801使序列递增的最小交换次数

    目录 题目要求 思路:状态机DP 实现一:状态机 Java C++ Rust 实现二:滚动数组 Java C++ Rust 总结 题目要求 思路:状态机DP 实现一:状态机 Java class Solution { public int minSwap(int[] nums1, int[] nums2) { int n = nums1.length; int[][] f = new int[n][2]; for (int i = 1; i < n; i++) f[i][0] = f[i][1]

  • java算法题解牛客BM99顺时针旋转矩阵示例

    目录 题目描述 解题思路 实践代码 解法1 解法2 题目描述 BM99 顺时针旋转矩阵 描述 有一个NxN整数矩阵,请编写一个算法,将矩阵顺时针旋转90度. 给定一个NxN的矩阵,和矩阵的阶数N,请返回旋转后的NxN矩阵. 数据范围:0<n<300,矩阵中的值满足0≤val≤1000 要求:空间复杂度 O(N^2),时间复杂度 O(N^2) 进阶:空间复杂度 O(1),时间复杂度 O(N^2) 示例1输入:[[1,2,3],[4,5,6],[7,8,9]],3返回值:[[7,4,1],[8,5

  • java算法题解Leetcode15三数之和实例

    目录 题目 解题思路 题目 15. 三数之和 给你一个包含 n 个整数的数组 nums,判断 nums 中是否存在三个元素 a,b,c ,使得 a + b + c = 0 ?请你找出所有和为 0 且不重复的三元组. 注意:答案中不可以包含重复的三元组. 示例 1:输入:nums = [-1,0,1,2,-1,-4]输出:[[-1,-1,2],[-1,0,1]]示例 2:输入:nums = []输出:[]示例 3:输入:nums = [0]输出:[]提示:0 <= nums.length <=

  • 后端算法题解LeetCode前缀和示例详解

    目录 面试题 01.09. 字符串轮转 方法一:模拟 思路 题解 方法二:搜索子字符串 思路 题解 1480. 一维数组的动态和 方法一:前缀和 思路 题解 724. 寻找数组的中心下标 方法一:前缀和 思路 解题 面试题 01.09. 字符串轮转 面试题 01.09. 字符串轮转 难度:easy 字符串轮转.给定两个字符串 s1 和 s2,请编写代码检查 s2 是否为 s1 旋转而成(比如,waterbottle 是 erbottlewat 旋转后的字符串). 示例1: 输入:s1 = "wa

  • Java排序算法总结之冒泡排序

    本文实例讲述了Java排序算法总结之冒泡排序.分享给大家供大家参考.具体分析如下: 前言:冒泡排序(BubbleSort)就是依次比较相邻的两个数,将小数放在前面,大数放在后面. 下面让我们一起    来看冒泡排序在Java中的算法实现. 冒泡排序是计算机的一种排序方法,它的时间复杂度为O(n^2),虽然不及堆排序.快速排序的O(nlogn,底数为2),但是有两个优点: 1."编程复杂度"很低,很容易写出代码: 2.具有稳定性,这里的稳定性是指原序列中相同元素的相对顺序仍然保持到排序后

随机推荐