【题解】—— LeetCode一周小结17

news2024/11/27 0:00:03

【题解】—— 每日一道题目栏


上接:【题解】—— LeetCode一周小结16

22.组合总和 Ⅳ

题目链接:377. 组合总和 Ⅳ

给你一个由 不同 整数组成的数组 nums ,和一个目标整数 target 。请你从 nums 中找出并返回总和为 target 的元素组合的个数。

题目数据保证答案符合 32 位整数范围。

示例 1:

输入:nums = [1,2,3], target = 4

输出:7

解释:

所有可能的组合为:

(1, 1, 1, 1)

(1, 1, 2)

(1, 2, 1)

(1, 3)

(2, 1, 1)

(2, 2)

(3, 1)

请注意,顺序不同的序列被视作不同的组合。

示例 2:

输入:nums = [9], target = 3

输出:0

提示:

1 <= nums.length <= 200

1 <= nums[i] <= 1000

nums 中的所有元素 互不相同

1 <= target <= 1000

题解:
方法:递归 记忆化搜索 动态规划
        

class Solution {
    public int combinationSum4(int[] nums, int target) {
        int[] memo = new int[target + 1];
        Arrays.fill(memo, -1); // -1 表示没有计算过
        return dfs(target, nums, memo);
    }

    private int dfs(int i, int[] nums, int[] memo) {
        if (i == 0) { // 爬完了
            return 1;
        }
        if (memo[i] != -1) { // 之前计算过
            return memo[i];
        }
        int res = 0;
        for (int x : nums) { // 枚举所有可以爬的台阶数
            if (x <= i) {
                res += dfs(i - x, nums, memo);
            }
        }
        return memo[i] = res; // 记忆化
    }
}

23.爱生气的书店老板

题目链接:1052. 爱生气的书店老板

有一个书店老板,他的书店开了 n 分钟。每分钟都有一些顾客进入这家商店。给定一个长度为 n 的整数数组 customers ,其中 customers[i] 是在第 i 分钟开始时进入商店的顾客数量,所有这些顾客在第 i 分钟结束后离开。

在某些时候,书店老板会生气。 如果书店老板在第 i 分钟生气,那么 grumpy[i] = 1,否则 grumpy[i] = 0。

当书店老板生气时,那一分钟的顾客就会不满意,若老板不生气则顾客是满意的。

书店老板知道一个秘密技巧,能抑制自己的情绪,可以让自己连续 minutes 分钟不生气,但却只能使用一次。

请你返回 这一天营业下来,最多有多少客户能够感到满意 。

示例 1:

输入:customers = [1,0,1,2,1,1,7,5], grumpy = [0,1,0,1,0,1,0,1], minutes
= 3

输出:16

解释:书店老板在最后 3 分钟保持冷静。

感到满意的最大客户数量 = 1 + 1 + 1 + 1 + 7 + 5 = 16.

示例 2:

输入:customers = [1], grumpy = [0], minutes = 1

输出:1

提示:

n == customers.length == grumpy.length

1 <= minutes <= n <= 2 * 104

0 <= customers[i] <= 1000

grumpy[i] == 0 or 1

题解:
方法:滑动窗口
        本题可以拆分成两个问题:

  1. 老板不生气时的顾客数量之和 s0。这些顾客可以感到满意。
  2. 长度为 minutes 的连续子数组中,老板生气时的顾客数量之和 s1的最大值 maxS1。这些顾客可以感到满意。
    最终答案为 s0+maxS1。
class Solution {
    public int maxSatisfied(int[] customers, int[] grumpy, int minutes) {
        int[] s = new int[2];
        int maxS1 = 0;
        for (int i = 0; i < customers.length; i++) {
            s[grumpy[i]] += customers[i];
            if (i < minutes - 1) { // 窗口长度不足 minutes
                continue;
            }
            maxS1 = Math.max(maxS1, s[1]);
            // 窗口最左边元素离开窗口
            s[1] -= grumpy[i - minutes + 1] > 0 ? customers[i - minutes + 1] : 0;
        }
        return s[0] + maxS1;
    }
}

24.感染二叉树需要的总时间

题目链接:2385. 感染二叉树需要的总时间

给你一棵二叉树的根节点 root ,二叉树中节点的值 互不相同 。另给你一个整数 start 。在第 0 分钟,感染 将会从值为 start 的节点开始爆发。

每分钟,如果节点满足以下全部条件,就会被感染:

节点此前还没有感染。
节点与一个已感染节点相邻。
返回感染整棵树需要的分钟数。

示例 1:

在这里插入图片描述

输入:root = [1,5,3,null,4,10,6,9,2], start = 3

输出:4

解释:节点按以下过程被感染:

  • 第 0 分钟:节点 3
  • 第 1 分钟:节点 1、10、6
  • 第 2 分钟:节点5
  • 第 3 分钟:节点 4
  • 第 4 分钟:节点 9 和 2

感染整棵树需要 4 分钟,所以返回 4 。

示例 2:

在这里插入图片描述

输入:root = [1], start = 1

输出:0

解释:第 0 分钟,树中唯一一个节点处于感染状态,返回 0 。

提示:

树中节点的数目在范围 [1, 105] 内

1 <= Node.val <= 105

每个节点的值 互不相同

树中必定存在值为 start 的节点

题解:
方法:DFS
        

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode() : val(0), left(nullptr), right(nullptr) {}
 *     TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
 *     TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
 * };
 */
class Solution {
    private TreeNode startNode;
    private final Map<TreeNode, TreeNode> fa = new HashMap<>();

    public int amountOfTime(TreeNode root, int start) {
        dfs(root, null, start);
        return maxDepth(startNode, startNode);
    }

    private void dfs(TreeNode node, TreeNode from, int start) {
        if (node == null) {
            return;
        }
        fa.put(node, from); // 记录每个节点的父节点
        if (node.val == start) {
            startNode = node; // 找到 start
        }
        dfs(node.left, node, start);
        dfs(node.right, node, start);
    }

    private int maxDepth(TreeNode node, TreeNode from) {
        if (node == null) {
            return -1; // 注意这里是 -1,因为 start 的深度为 0
        }
        int res = -1;
        if (node.left != from) {
            res = Math.max(res, maxDepth(node.left, node));
        }
        if (node.right != from) {
            res = Math.max(res, maxDepth(node.right, node));
        }
        if (fa.get(node) != from) {
            res = Math.max(res, maxDepth(fa.get(node), node));
        }
        return res + 1;
    }
}

25.总行驶距离

题目链接:2739. 总行驶距离

卡车有两个油箱。给你两个整数,mainTank 表示主油箱中的燃料(以升为单位),additionalTank 表示副油箱中的燃料(以升为单位)。

该卡车每耗费 1 升燃料都可以行驶 10 km。每当主油箱使用了 5 升燃料时,如果副油箱至少有 1 升燃料,则会将 1 升燃料从副油箱转移到主油箱。

返回卡车可以行驶的最大距离。

注意:从副油箱向主油箱注入燃料不是连续行为。这一事件会在每消耗 5 升燃料时突然且立即发生。

示例 1:

输入:mainTank = 5, additionalTank = 10

输出:60

解释:

在用掉 5 升燃料后,主油箱中燃料还剩下 (5 - 5 + 1) = 1 升,行驶距离为 50km 。

在用掉剩下的 1 升燃料后,没有新的燃料注入到主油箱中,主油箱变为空。

总行驶距离为 60km 。

示例 2:

输入:mainTank = 1, additionalTank = 2

输出:10

解释:

在用掉 1 升燃料后,主油箱变为空。

总行驶距离为 10km 。

提示:

1 <= mainTank, additionalTank <= 100

题解:
方法:模拟
        

class Solution {
    public int distanceTraveled(int mainTank, int additionalTank) {
        int ans = 0;
        while (mainTank >= 5) {
            mainTank -= 5;
            ans += 50;
            if (additionalTank > 0) {
                additionalTank--;
                mainTank++;
            }
        }
        return ans + mainTank * 10;
    }
}

方法:快速模拟
        

class Solution {
    public int distanceTraveled(int mainTank, int additionalTank) {
        int ans = 0;
        while (mainTank >= 5) {
            int t = mainTank / 5;
            ans += t * 50;
            mainTank %= 5;
            t = Math.min(t, additionalTank);
            additionalTank -= t;
            mainTank += t;
        }
        return ans + mainTank * 10;
    }
}


26.快照数组

题目链接:1146. 快照数组

实现支持下列接口的「快照数组」- SnapshotArray:

SnapshotArray(int length) - 初始化一个与指定长度相等的 类数组 的数据结构。初始时,每个元素都等于 0。
void set(index, val) - 会将指定索引 index 处的元素设置为 val。
int snap() - 获取该数组的快照,并返回快照的编号 snap_id(快照号是调用 snap() 的总次数减去 1)。
int get(index, snap_id) - 根据指定的 snap_id 选择快照,并返回该快照指定索引 index 的值。

示例:

输入:[“SnapshotArray”,“set”,“snap”,“set”,“get”]

[[3],[0,5],[],[0,6],[0,0]]

输出:[null,null,0,null,5]

解释:

SnapshotArray snapshotArr = new SnapshotArray(3); // 初始化一个长度为 3 的快照数组

snapshotArr.set(0,5); // 令 array[0] = 5

snapshotArr.snap(); // 获取快照,返回 snap_id = 0

snapshotArr.set(0,6);

snapshotArr.get(0,0); // 获取 snap_id = 0 的快照中 array[0] 的值,返回 5

提示:

1 <= length <= 50000

题目最多进行50000 次set,snap,和 get的调用 。

0 <= index < length

0 <= snap_id < 我们调用 snap() 的总次数

0 <= val <= 10^9

题解:
方法:哈希表 二分查找
        

class SnapshotArray {
    // 当前快照编号,初始值为 0
    private int curSnapId;

    // 每个 index 的历史修改记录
    private final Map<Integer, List<int[]>> history = new HashMap<>();

    public SnapshotArray(int length) {
    }

    public void set(int index, int val) {
        history.computeIfAbsent(index, k -> new ArrayList<>()).add(new int[]{curSnapId, val});
    }

    public int snap() {
        return curSnapId++;
    }

    public int get(int index, int snapId) {
        if (!history.containsKey(index)) {
            return 0;
        }
        List<int[]> h = history.get(index);
        int j = search(h, snapId);
        return j < 0 ? 0 : h.get(j)[1];
    }

    // 返回最大的下标 i,满足 h[i][0] <= x
    // 如果不存在则返回 -1
    private int search(List<int[]> h, int x) {
        // 开区间 (left, right)
        int left = -1;
        int right = h.size();
        while (left + 1 < right) { // 区间不为空
            // 循环不变量:
            // h[left][0] <= x
            // h[right][1] > x
            int mid = left + (right - left) / 2;
            if (h.get(mid)[0] <= x) {
                left = mid; // 区间缩小为 (mid, right)
            } else {
                right = mid; // 区间缩小为 (left, mid)
            }
        }
        // 根据循环不变量,此时 h[left][0] <= x 且 h[left+1][0] = h[right][0] > x
        // 所以 left 是最大的满足 h[left][0] <= x 的下标
        // 如果不存在,则 left 为其初始值 -1
        return left;
    }
}


/**
 * Your SnapshotArray object will be instantiated and called as such:
 * SnapshotArray* obj = new SnapshotArray(length);
 * obj->set(index,val);
 * int param_2 = obj->snap();
 * int param_3 = obj->get(index,snap_id);
 */

27.查询网格图中每一列的宽度

题目链接:2639. 查询网格图中每一列的宽度

给你一个下标从 0 开始的 m x n 整数矩阵 grid 。矩阵中某一列的宽度是这一列数字的最大 字符串长度 。

比方说,如果 grid = [[-10], [3], [12]] ,那么唯一一列的宽度是 3 ,因为 -10 的字符串长度为 3 。
请你返回一个大小为 n 的整数数组 ans ,其中 ans[i] 是第 i 列的宽度。

一个有 len 个数位的整数 x ,如果是非负数,那么 字符串长度 为 len ,否则为 len + 1 。

示例 1:

输入:grid = [[1],[22],[333]]

输出:[3]

解释:第 0 列中,333 字符串长度为 3 。

示例 2:

输入:grid = [[-15,1,3],[15,7,12],[5,6,-2]]

输出:[3,1,2]

解释:

第 0 列中,只有 -15 字符串长度为 3 。

第 1 列中,所有整数的字符串长度都是 1 。

第 2 列中,12 和 -2 的字符串长度都为 2 。

提示:

m == grid.length

n == grid[i].length

1 <= m, n <= 100

-109 <= grid[r][c] <= 109

题解:
方法:数学
        遍历每一列,求出数字转成字符串后的最大长度。

class Solution {
    public int[] findColumnWidth(int[][] grid) {
        int n = grid[0].length;
        int[] ans = new int[n];
        for (int j = 0; j < n; j++) {
            for (int[] row : grid) {
                ans[j] = Math.max(ans[j], Integer.toString(row[j]).length());
            }
        }
        return ans;
    }
}

        也可以手动计算长度。

class Solution {
    public int[] findColumnWidth(int[][] grid) {
        int n = grid[0].length;
        int[] ans = new int[n];
        for (int j = 0; j < n; j++) {
            for (int[] row : grid) {
                int len = row[j] <= 0 ? 1 : 0;
                for (int x = row[j]; x != 0; x /= 10) {
                    len++;
                }
                ans[j] = Math.max(ans[j], len);
            }
        }
        return ans;
    }
}

优化
        

class Solution {
    public int[] findColumnWidth(int[][] grid) {
        int n = grid[0].length;
        int[] ans = new int[n];
        for (int j = 0; j < n; j++) {
            int mn = 0;
            int mx = 0;
            for (int[] row : grid) {
                mn = Math.min(mn, row[j]);
                mx = Math.max(mx, row[j]);
            }
            int len = 1;
            for (int x = Math.max(mx / 10, -mn); x > 0; x /= 10) {
                len++;
            }
            ans[j] = len;
        }
        return ans;
    }
}

28.负二进制转换

题目链接:1017. 负二进制转换

给你一个整数 n ,以二进制字符串的形式返回该整数的 负二进制(base -2)表示。

注意,除非字符串就是 “0”,否则返回的字符串中不能含有前导零。

示例 1:

输入:n = 2

输出:“110”

解释:(-2)2 + (-2)1 = 2

示例 2:

输入:n = 3

输出:“111”

解释:(-2)2 + (-2)1 + (-2)0 = 3

示例 3:

输入:n = 4

输出:“100”

解释:(-2)2 = 4

提示:

0 <= n <= 109

题解:
方法:模拟 数学
        进制转换取余必须为正数

class Solution {
    public String baseNeg2(int n) {
        if(n == 0)return "0";   // 0直接返回
        StringBuilder res = new StringBuilder();
        // 类似十进制转二进制的方法,只是余数如果为负数需要修正
        while(n != 0){
            int mod = n % (-2);
            n = n / (-2);
            if(mod == -1){
                // 修正余数为-1->1,对应商也要加1
                n++;
                mod = 1;
            }
            res.append(mod);
        }
        return res.reverse().toString();     // 生成的二进制是逆序的,需要反转
    }
}

下接:【题解】—— LeetCode一周小结18


本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1632034.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

01.Kafka简介与基本概念介绍

1 Kafka 简介 Kafka 是最初由 Linkedin公司开发&#xff0c;是一个分布式、支持分区(partition)的、多副本(replica)的&#xff0c;基于 Zookeeper 协调的分布式消息系统&#xff0c;它的最大的特性就是可以实时的处理大量数据以满足各种需求场景&#xff1a;比如基于 hadoop 的…

SpringBoot 快速开始 Dubbo RPC

文章目录 SpringBoot 快速开始 Dubbo RPC下载 Nacos项目启动项目的创建创建主项目接口定义服务的创建Dubbo 服务提供者的创建服务的消费者创建 添加依赖给 Provider、Consumer 添加依赖 开始写代码定义接口在 Provider 中实现在 Consumer 里面使用创建启动类 注册中心配置启动 …

R-Tree: 原理及实现代码

文章目录 R-Tree: 原理及实现代码1. R-Tree 原理1.1 R-Tree 概述1.2 R-Tree 结构1.3 R-Tree 插入与查询 2. R-Tree 实现代码示例&#xff08;Python&#xff09;结语 R-Tree: 原理及实现代码 R-Tree 是一种用于管理多维空间数据的数据结构&#xff0c;常用于数据库系统和地理信…

党建3d互动虚拟现实网上展厅有何优势?

在数字化浪潮席卷全球的今天&#xff0c;企业如何迅速踏上虚拟世界的征程&#xff0c;开启元宇宙之旅?答案就是——3D虚拟云展。这一创新平台&#xff0c;华锐视点以虚拟现实技术和3D数字建模为基石提供3D云展搭建服务&#xff0c;助力企业轻松搭建起虚拟数字基础设施&#xf…

Rust Web开发实战:打造高效稳定的服务端应用

Rust Web开发实战&#xff1a;打造高效稳定的服务端应用 本书将带领您从零开始构建Web应用程序&#xff0c;无论是API、微服务还是单体应用&#xff0c;都将一一涵盖。您将学到如何优雅地对外开放API&#xff0c;如何连接数据库以安全存储数据&#xff0c;以及如何对应用程序进…

用结构体把驱动层和应用层分开

用正点原子代码的usmart分析&#xff0c;如下&#xff1a; usmart.h usmart_config.c 实例&#xff1a;把结构体与具体驱动绑定一起 /* 正点原子的usmart串口的封装 涉及文件&#xff1a;usmart.h usmart.c usmart_config.c 还有外面使用的文件&#xff08;应用层调用&#xff…

Rocketmq 5 分级存储 Tieredstore(RIP-57、RIP-65) 原理详解 源码解析

1. 背景 RocketMQ 5.x 的演进目标之一是云原生化&#xff0c;在云原生和 Serverless 的浪潮下&#xff0c;需要解决 RocketMQ 存储层存在两个瓶颈。 数据量膨胀过快&#xff0c;单体硬件无法支撑存储的低成本和速度无法兼得 众多云厂商也希望提供 Serverless 化的 RocketMQ …

【源码阅读】 Golang中的database/sql库源码探究

Note&#xff1a;文章待完结 文章目录 前言一、整体目录结构二、driver包1、驱动相关driver.Driver2、驱动连接&#xff1a;driver.Conn3、预处理结构&#xff1a;Stmt4、执行结果 driver.Result5、查询结果&#xff1a;driver.Rows6、driver.RowsAffected7、driver.Value8、Va…

IDEA主题美化【保姆级】

前言 一款好的 IDEA 主题虽然不能提高我们的开发效率&#xff0c;但一个舒适简单的主题可以使开发人员更舒适的开发&#xff0c;时常换一换主题可以带来不一样的体验&#xff0c;程序员的快乐就这么简单。话不多说&#xff0c;先上我自己认为好看的主题设置。 最终效果图: 原…

《我们为什么爱喝酒》酒精如何决定人类社会成败 - 三余书屋 3ysw.net

我们为什么爱喝酒&#xff1a;酒精如何决定人类社会成败 大家好&#xff0c;今天我们要解读的书是《我们为什么爱喝酒&#xff1f;》&#xff0c;副标题是“酒精如何决定人类社会成败”。你平时会喝酒吗&#xff1f;你如何看待“喝酒有害健康”这一观点&#xff1f;欢迎在评论…

stm32单片机开发三、DMA

DMA其实就是一种将ADC的数据寄存器、串口的数据寄存器等等一些数据放到sram中特定位置&#xff0c;方便CPU去读取 比如ADC转换&#xff0c;DMA直接转换的ADC的值放在内存中的特定位置&#xff0c;CPU可以直接去读取 uint16_t AD_Value[4]; //定义用于存放AD转换结果的全局…

如何让用户听话?

​福格教授&#xff08;斯坦福大学行为设计实验室创始人&#xff09;通过深入研究人类行为20年&#xff0c;2007年用自己的名子命名&#xff0c;提出了一个行为模型&#xff1a;福格行为模型。 模型表明&#xff1a;人的行为发生&#xff0c;要有做出行为的动机和完成行为的能…

在IDEA中使用.env文件导入系统配置的图文教程

JetBrains的IDEA是一款功能强大的集成开发环境&#xff0c;为开发人员提供了丰富的功能和工具。使用.env文件来管理配置信息在IDEA中非常简单。 旧版本默认支持&#xff0c;新版本idea需要安装插件才可以。 这里我们可以安装EnvFile插件&#xff0c;步骤如下&#xff1a; 在弹…

回归预测 | Matlab实现NGO-ESN北方苍鹰算法优化回声状态网络多输入单输出回归预测

回归预测 | Matlab实现NGO-ESN北方苍鹰算法优化回声状态网络多输入单输出回归预测 目录 回归预测 | Matlab实现NGO-ESN北方苍鹰算法优化回声状态网络多输入单输出回归预测预测效果基本介绍程序设计参考资料 预测效果 基本介绍 1.Matlab实现NGO-ESN北方苍鹰算法优化回声状态网络…

利用NetBIOS欺骗攻击盗取hash(2)

LLMNR和NetBIOS欺骗 原理探究 在使用传输控制协议 (TCP) 和互联网协议 (IP) 堆栈的网络&#xff08;包括当今大多数网络&#xff09;上&#xff0c;需要将资源名称转换为 IP 地址以连接到这些资源。因此&#xff0c;网络需要将“resource.domain.com”解析为“xxxx”的 IP 地…

书生·浦语 大模型(学习笔记-9)大模型微调的相关概念 预训练 与 微调 全量微调FFT 与 PEFT的区别

目录 一、什么是大模型微调 二、指令微调 三、微调的目的 三、微调的方式 四、微调的步骤 五、微调数据准备 六、微调的数据质量 一、什么是大模型微调 预训练和微调的区别&#xff0c;这个很关键 二、指令微调 这个地方主要是微调的角度不同&#xff0c;简单理解&#…

(学习日记)2024.04.20:UCOSIII第四十八节:各文件功能概览

之前的章节都是针对某个或某些知识点进行的专项讲解&#xff0c;重点在功能和代码解释。 回到最初开始学μC/OS-III系统时&#xff0c;当时就定下了一个目标&#xff0c;不仅要读懂&#xff0c;还要读透&#xff0c;改造成更适合中国宝宝体质的使用方式。在学完野火的教程后&a…

leetcode-包含min函数的栈-93

题目要求 题目思路 1.设计上两个栈&#xff0c;第一个栈s1里面正常存储插入进来的数据&#xff0c;s2里面只存储s1里面最小的那个数据。 2.对于push函数&#xff0c;所有新来的value都需要在s1中插入&#xff0c;s2中&#xff0c;如果s2为空&#xff0c;那么也直接插入&#x…

基于Springboot+Vue的Java项目-火车票订票系统开发实战(附演示视频+源码+LW)

大家好&#xff01;我是程序员一帆&#xff0c;感谢您阅读本文&#xff0c;欢迎一键三连哦。 &#x1f49e;当前专栏&#xff1a;Java毕业设计 精彩专栏推荐&#x1f447;&#x1f3fb;&#x1f447;&#x1f3fb;&#x1f447;&#x1f3fb; &#x1f380; Python毕业设计 &am…

Docker | 入门:安装与配置

Docker | 入门&#xff1a;安装与配置 Docker 和传统虚拟机区别 对于传统虚拟机&#xff1a; 虚拟出一套硬件&#xff0c;运行一个完整的操作系统&#xff0c;并在这个操作系统上安装和运行软件。 对于 Docker: 将一个个容器隔离开。 容器内的应用直接运行在宿主机的内容&am…