当前位置: 首页 > news >正文

算法刷题记录——LeetCode篇(8) [第701~800题](持续更新)

(优先整理热门100及面试150,不定期持续更新,欢迎关注)


739. 每日温度

给定一个整数数组 temperatures ,表示每天的温度,返回一个数组 answer ,其中 answer[i] 是指对于第 i 天,下一个更高温度出现在几天后。如果气温在这之后都不会升高,请在该位置用 0 来代替。

示例 1:

输入: temperatures = [73,74,75,71,69,72,76,73]
输出: [1,1,4,2,1,1,0,0]

示例 2:

输入: temperatures = [30,40,50,60]
输出: [1,1,1,0]

示例 3:

输入: temperatures = [30,60,90]
输出: [1,1,0]

提示:

  • 1 <= temperatures.length <= 10^5
  • 30 <= temperatures[i] <= 100

方法一:单调栈

使用单调栈维护一个递减的温度序列索引。遍历数组时,若当前温度高于栈顶索引对应的温度,则弹出栈顶元素并计算天数差。

代码实现(Java)

class Solution {
    public int[] dailyTemperatures(int[] temperatures) {
        int n = temperatures.length;
        int[] answer = new int[n];
        Deque<Integer> stack = new ArrayDeque<>(); // 维护温度索引的单调递减栈
        
        for (int i = 0; i < n; i++) {
            // 当前温度高于栈顶温度时,计算天数差并更新结果
            while (!stack.isEmpty() && temperatures[i] > temperatures[stack.peek()]) {
                int prevIndex = stack.pop();
                answer[prevIndex] = i - prevIndex;
            }
            stack.push(i); // 当前温度入栈
        }
        return answer;
    }
}

方法二:跳跃法(从后往前动态规划)

从后往前遍历数组,利用已知结果跳过不必要的比较。若后一天温度更高则直接记录,否则根据后一天的结果跳跃到可能更高的温度位置。

代码实现(Java)

class Solution {
    public int[] dailyTemperatures(int[] temperatures) {
        int n = temperatures.length;
        int[] answer = new int[n];
        answer[n - 1] = 0; // 最后一天不会有更高的温度
        for (int i = n - 2; i >= 0; i--) {
            int j = i + 1;
            while (j < n) {
                if (temperatures[j] > temperatures[i]) {
                    answer[i] = j - i;
                    break;
                } else if (answer[j] == 0) {
                    answer[i] = 0;
                    break;
                } else {
                    j += answer[j]; // 跳跃到可能更高的温度位置
                }
            }
        }
        return answer;
    }
}

复杂度分析

  • 单调栈:时间复杂度O(n),空间复杂度O(n)。维护一个递减栈,确保每个元素入栈和出栈各一次,高效找到下一个更高温度。
  • 跳跃法:时间复杂度O(n),空间复杂度O(n)。从后向前利用已有结果跳跃比较,减少重复遍历,同样高效。

763. 划分字母区间

给你一个字符串 s 。我们要把这个字符串划分为尽可能多的片段,同一字母最多出现在一个片段中。例如,字符串 "ababcc" 能够被分为 ["abab", "cc"],但类似 ["aba", "bcc"]["ab", "ab", "cc"] 的划分是非法的。

注意,划分结果需要满足:将所有划分结果按顺序连接,得到的字符串仍然是 s

返回一个表示每个字符串片段的长度的列表。

示例 1:

输入:s = "ababcbacadefegdehijhklij"
输出:[9,7,8]

划分结果为 “ababcbaca”、“defegde”、“hijhklij” 。每个字母最多出现在一个片段中。
像 “ababcbacadefegde”, “hijhklij” 这样的划分是错误的,因为划分的片段数较少。

示例 2:

输入:s = "eccbbbbdec"
输出:[10]

提示:

  • 1 <= s.length <= 500
  • s 仅由小写英文字母组成

方法一:贪心算法

  1. 记录每个字符的最后出现位置:首先遍历字符串,记录每个字符最后一次出现的索引,为后续分割提供依据。
  2. 维护当前片段的起止位置:再次遍历字符串,动态维护当前片段的结束位置,确保所有已遍历字符的最后出现位置均包含在当前片段中。当遍历到当前片段的结束位置时,立即分割,确保每个字符仅属于一个片段,并开始下一个片段的处理。

代码实现(Java)

class Solution {
    public List<Integer> partitionLabels(String s) {
        // 记录每个字符的最后出现位置
        int[] lastOccurrence = new int[26];
        int length = s.length();
        for (int i = 0; i < length; i++) {
            char c = s.charAt(i);
            lastOccurrence[c - 'a'] = i;
        }
      
        List<Integer> partitions = new ArrayList<>();
        int start = 0, end = 0;
        for (int i = 0; i < length; i++) {
            char currentChar = s.charAt(i);
            // 扩展当前片段的结束位置
            end = Math.max(end, lastOccurrence[currentChar - 'a']);
            // 当遍历到当前片段的结束位置时,分割并记录
            if (i == end) {
                partitions.add(end - start + 1);
                start = end + 1; // 下一个片段的起始位置
            }
        }
        return partitions;
    }
}

动态规划法复杂度分析:

  • 时间复杂度O(n),其中 n 是字符串的长度。两次遍历字符串的时间复杂度均为 O(n)
  • 空间复杂度O(1),使用固定大小的数组存储字符的最后出现位置。

方法二:合并区间(理论补充)

  1. 生成字符区间:记录每个字符的首次和最后一次出现的位置,生成区间集合。
  2. 合并重叠区间:将所有重叠的区间合并,合并后的每个区间对应一个最终的分段。

合并区间法复杂度分析:

  • 时间复杂度O(n + m log m),其中 m 是不同字符的数量(最多26个),实际性能不如贪心算法。
  • 空间复杂度O(m),需要存储所有字符的区间。

博客源文件Gitee仓库:

gitee.com/richardmilos/allen-csdn-notes

(持续更新,未完待续)

相关文章:

  • 关于Redis的集群(上)
  • java构建树形结构的方式、如何组装树状结构数据
  • ModBus TCP/RTU互转(主)(从)|| Modbus主动轮询下发的工业应用 || 基于智能网关的串口服务器进行Modbus数据收发的工业应用
  • 课程4. 图像处理算法与卷积神经网络
  • js核心运行逻辑
  • Vue的虚拟DOM算法准确来讲应该是叫做“snabbdom”或者--“diff算法”之类
  • 分布式全局ID生成方案
  • 集成电路设计、制造和测试之旅
  • Lua 数据类型
  • vue2实现可拖拽菜单栏,及根据菜单内容自动扩展宽度
  • 论文阅读:2023-arxiv Can AI-Generated Text be Reliably Detected?
  • Ubuntu22.04虚拟机里安装Yolov8流程
  • 使用redis客户端中对于json数据格式的存储和读取
  • 在LORA训练中,LORA模型的矩阵的行列是多少
  • 【ARM中R0寄存器】
  • 基于k3s部署Nginx、MySQL、Golang和Redis的详细教程
  • 文件解析漏洞
  • 协程池是调用端并发请求的缓释胶囊
  • 每日定投40刀BTC(9)20250312 - 20250315
  • 剑指 Offer II 078. 合并排序链表
  • 烟花秀、新航线、购物节......上海邮轮文化旅游节今日开幕
  • 兴业银行一季度净赚超237亿降逾2%,营收降逾3%
  • 游客曝九寨沟打网约车被出租车围堵,景区回应:当地无合规网约车
  • 邮储银行一季度净赚超252亿降逾2%,营收微降
  • 新经济与法|如何治理网购刷单与控评?数据合规管理是关键
  • 大家聊中国式现代化|陶希东:打造高水平安全韧性城市,给群众看得见的安全感