力扣热门算法题 174. 地下城游戏,189. 轮转数组,198. 打家劫舍

news2024/10/6 19:15:22

174. 地下城游戏,189. 轮转数组,198. 打家劫舍,每题做详细思路梳理,配套Python&Java双语代码, 2024.03.31 可通过leetcode所有测试用例。

目录

174. 地下城游戏

解题思路

完整代码

Python

Java

189. 轮转数组

解题思路

完整代码

Python

Java

198. 打家劫舍

解题思路

完整代码

Python

Java


174. 地下城游戏

        恶魔们抓住了公主并将她关在了地下城 dungeon 的 右下角 。地下城是由 m * n 个房间组成的二维网格。我们英勇的骑士最初被安置在 左上角 的房间里,他必须穿过地下城并通过对抗恶魔来拯救公主。

        骑士的初始健康点数为一个正整数。如果他的健康点数在某一时刻降至 0 或以下,他会立即死亡。

        有些房间由恶魔守卫,因此骑士在进入这些房间时会失去健康点数(若房间里的值为负整数,则表示骑士将损失健康点数);其他房间要么是空的(房间里的值为 0),要么包含增加骑士健康点数的魔法球(若房间里的值为正整数,则表示骑士将增加健康点数)。

为了尽快解救公主,骑士决定每次只 向右 或 向下 移动一步。

返回确保骑士能够拯救到公主所需的最低初始健康点数。

        注意:任何房间都可能对骑士的健康点数造成威胁,也可能增加骑士的健康点数,包括骑士进入的左上角房间以及公主被监禁的右下角房间。

示例 1:

输入:dungeon = [[-2,-3,3],[-5,-10,1],[10,30,-5]]
输出:7
解释:如果骑士遵循最佳路径:右 -> 右 -> 下 -> 下 ,则骑士的初始健康点数至少为 7 。

示例 2:

输入:dungeon = [[0]]
输出:1

解题思路

恶魔们抓住了公主并将她关在了地下城 dungeon 的 右下角 。地下城是由 m x n 个房间组成的二维网格。我们英勇的骑士最初被安置在 左上角 的房间里,他必须穿过地下城并通过对抗恶魔来拯救公主。

骑士的初始健康点数为一个正整数。如果他的健康点数在某一时刻降至 0 或以下,他会立即死亡。

有些房间由恶魔守卫,因此骑士在进入这些房间时会失去健康点数(若房间里的值为负整数,则表示骑士将损失健康点数);其他房间要么是空的(房间里的值为 0),要么包含增加骑士健康点数的魔法球(若房间里的值为正整数,则表示骑士将增加健康点数)。

为了尽快解救公主,骑士决定每次只 向右 或 向下 移动一步。

返回确保骑士能够拯救到公主所需的最低初始健康点数。

注意:任何房间都可能对骑士的健康点数造成威胁,也可能增加骑士的健康点数,包括骑士进入的左上角房间以及公主被监禁的右下角房间。

示例 1:

输入:dungeon = [[-2,-3,3],[-5,-10,1],[10,30,-5]]
输出:7
解释:如果骑士遵循最佳路径:右 -> 右 -> 下 -> 下 ,则骑士的初始健康点数至少为 7 。

示例 2:

输入:dungeon = [[0]]
输出:1

完整代码

Python
class Solution:
    def calculateMinimumHP(self, dungeon: List[List[int]]) -> int:
        m, n = len(dungeon), len(dungeon[0])
        dp = [[float('inf')] * (n + 1) for _ in range(m + 1)]
        dp[m][n - 1] = dp[m - 1][n] = 1

        for i in range(m - 1, -1, -1):
            for j in range(n - 1, -1, -1):
                min_health = min(dp[i + 1][j], dp[i][j + 1]) - dungeon[i][j]
                dp[i][j] = max(1, min_health)

        return dp[0][0]
Java
class Solution {
    public int calculateMinimumHP(int[][] dungeon) {
        int m = dungeon.length, n = dungeon[0].length;
        int[][] dp = new int[m + 1][n + 1];
        for (int i = 0; i <= m; ++i) Arrays.fill(dp[i], Integer.MAX_VALUE);
        dp[m][n - 1] = dp[m - 1][n] = 1;

        for (int i = m - 1; i >= 0; --i) {
            for (int j = n - 1; j >= 0; --j) {
                int minHealth = Math.min(dp[i + 1][j], dp[i][j + 1]) - dungeon[i][j];
                dp[i][j] = Math.max(1, minHealth);
            }
        }

        return dp[0][0];
    }

}

189. 轮转数组

给定一个整数数组 nums,将数组中的元素向右轮转 k 个位置,其中 k 是非负数。

示例 1:

输入: nums = [1,2,3,4,5,6,7], k = 3
输出: [5,6,7,1,2,3,4]
解释:
向右轮转 1 步: [7,1,2,3,4,5,6]
向右轮转 2 步: [6,7,1,2,3,4,5]
向右轮转 3 步: [5,6,7,1,2,3,4]

示例 2:

输入:nums = [-1,-100,3,99], k = 2
输出:[3,99,-1,-100]
解释: 
向右轮转 1 步: [99,-1,-100,3]
向右轮转 2 步: [3,99,-1,-100]

解题思路

解决这个问题的关键在于找到一种高效的方法来旋转数组,而不仅仅是简单地执行 k 次单步旋转。一种有效的方法是通过反转数组的部分来实现旋转效果。具体步骤如下:

  1. 反转整个数组:首先,将整个数组反转。这一步会将原本应该被移动到数组前面的元素移动到数组的后面。

  2. 反转数组的前 k 个元素:接着,反转数组中前 k 个元素。由于数组已经被整体反转过,这一步实际上是将那些应该位于数组前面的元素放到了正确的位置。

  3. 反转数组剩余部分:最后,反转数组中剩余的部分,即从索引 k 到数组结束的部分。这一步是将剩余的元素放到它们应该在的位置。

注意   由于 k 可能大于数组的长度,所以在进行操作之前需要将 k 对数组长度取模,以确保 k 在数组长度范围内。

完整代码

Python
class Solution:
    def rotate(self, nums: List[int], k: int) -> None:
        n = len(nums)
        k %= n

        def reverse(start, end):
            while start < end:
                nums[start], nums[end] = nums[end], nums[start]
                start, end = start + 1, end - 1

        reverse(0, n - 1)
        reverse(0, k - 1)
        reverse(k, n - 1)
Java
class Solution {
    public void rotate(int[] nums, int k) {
        int n = nums.length;
        k %= n;

        reverse(nums, 0, n - 1);
        reverse(nums, 0, k - 1);
        reverse(nums, k, n - 1);
    }

    private void reverse(int[] nums, int start, int end) {
        while (start < end) {
            int temp = nums[start];
            nums[start] = nums[end];
            nums[end] = temp;
            start++;
            end--;
        }
    }

}

198. 打家劫舍

你是一个专业的小偷,计划偷窃沿街的房屋。每间房内都藏有一定的现金,影响你偷窃的唯一制约因素就是相邻的房屋装有相互连通的防盗系统,如果两间相邻的房屋在同一晚上被小偷闯入,系统会自动报警

给定一个代表每个房屋存放金额的非负整数数组,计算你 不触动警报装置的情况下 ,一夜之内能够偷窃到的最高金额。

示例 1:

输入:[1,2,3,1]
输出:4
解释:偷窃 1 号房屋 (金额 = 1) ,然后偷窃 3 号房屋 (金额 = 3)。
     偷窃到的最高金额 = 1 + 3 = 4 。

示例 2:

输入:[2,7,9,3,1]
输出:12
解释:偷窃 1 号房屋 (金额 = 2), 偷窃 3 号房屋 (金额 = 9),接着偷窃 5 号房屋 (金额 = 1)。
     偷窃到的最高金额 = 2 + 9 + 1 = 12 。

解题思路

这个问题可以通过动态规划(Dynamic Programming, DP)来解决。我们可以定义一个一维数组 dp,其中 dp[i] 表示到达第 i 个房屋时能偷窃到的最高金额,注意这里的 i 是从 0 开始的索引。

解题步骤如下:

  1. 基本情况:当只有一间房屋时(即数组长度为 1),那么偷窃到的最高金额就是这间房屋中的金额。所以 dp[0] = nums[0](如果数组不为空)。

  2. 第二间房屋:当有两间房屋时,由于不能同时偷窃相邻的房屋,因此偷窃到的最高金额是这两间房屋中金额较大的那一个。所以 dp[1] = max(nums[0], nums[1])

  3. 状态转移方程:对于第 i 间房屋(i > 1),有两种选择:

    • 不偷窃第 i 间房屋,那么最高金额为到达前一间房屋时的最高金额,即 dp[i-1]
    • 偷窃第 i 间房屋,那么由于不能偷窃相邻的房屋,最高金额为第 i-2 间房屋的最高金额加上第 i 间房屋中的金额,即 dp[i-2] + nums[i]

    因此,状态转移方程为 dp[i] = max(dp[i-1], dp[i-2] + nums[i])

  4. 结果:数组 nums 中最后一个房屋的索引为 nums.length - 1,所以 dp[nums.length - 1] 就是不触动警报装置情况下能偷窃到的最高金额。

完整代码

Python
class Solution:
    def rob(self, nums: List[int]) -> int:
        if not nums:
            return 0
        if len(nums) == 1:
            return nums[0]

        dp = [0] * len(nums)
        dp[0], dp[1] = nums[0], max(nums[0], nums[1])

        for i in range(2, len(nums)):
            dp[i] = max(dp[i-1], dp[i-2] + nums[i])

        return dp[-1]
Java
class Solution {
    public int rob(int[] nums) {
        if (nums == null || nums.length == 0) {
            return 0;
        }
        if (nums.length == 1) {
            return nums[0];
        }
        
        int[] dp = new int[nums.length];
        dp[0] = nums[0];
        dp[1] = Math.max(nums[0], nums[1]);
        
        for (int i = 2; i < nums.length; i++) {
            dp[i] = Math.max(dp[i-1], dp[i-2] + nums[i]);
        }
        
        return dp[nums.length - 1];
    }

}

 

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

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

相关文章

【Web应用技术基础】JavaScript(1)——案例:猜数字

上一个博客发了视频。这个博客因为不能插入视频&#xff0c;所以给大家一张一张截图的 点击“重新开始一局游戏” <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><meta name"viewport" content"…

[leetcode]剑指 Offer 29. 顺时针打印矩阵

前言&#xff1a;剑指offer刷题系列 问题&#xff1a; 输入一个矩阵&#xff0c;按照从外向里以顺时针的顺序依次打印出每一个数字。 示例&#xff1a; 输入&#xff1a;matrix [[1,2,3],[4,5,6],[7,8,9]] 输出&#xff1a;[1,2,3,6,9,8,7,4,5]思路&#xff1a; 看到这个…

Lambda表达式,Stream流

文章目录 Lambda表达式作用前提函数式接口特点 语法省略模式和匿名对象类的区别 Stream流思想作用三类方法获取方法单列集合(Collection[List,Set双列集合Map(不能直接获取)数组同一类型元素(Stream中的静态方法) 常见的中间方法终结方法收集方法 Optional类 Lambda表达式 作用…

客户案例丨拓数派向量计算引擎PieCloudVector助力东吴证券AIGC应用升级

1.项目背景 随着人工智能技术的不断创新和应用&#xff0c;我们可以看到人工智能在各个领域的应用越来越广泛。深度学习技术在图像识别、语音识别、自然语言处理等领域表现出色。机器学习算法的改进将解决更多实际问题&#xff0c;如增强学习、迁移学习和联合学习等&#xff…

一个瓶盖和电子工程师以及机械工程师能有什么联系?

过小的产品空间是一种罪 我也曾经是喜欢将东西做的小巧&#xff0c;其实这是不归路&#xff0c;特别是对于产品&#xff0c;一不小心&#xff0c;就会发生可怕的问题. 最近某厂供应的一批一体机&#xff0c;设计上有严重缺陷&#xff0c;外壳做小了&#xff0c;散热孔开的太小…

什么是智慧驿站?智慧驿站有哪些功能?创新型智慧公厕解说

近年来&#xff0c;随着智能科技的迅速发展&#xff0c;人们对于城市生活的期望也逐渐提升。作为城市基础设施的一部分&#xff0c;智慧驿站应运而生。它不仅是一座智慧公厕&#xff0c;更是集合了多种功能&#xff0c;给我们带来全新的城市生活体验。本文以智慧驿站智慧公厕源…

使用Vite创建一个vue3项目

一、vite是什么&#xff1f; vite 是一种新型前端构建工具&#xff0c;能够显著提升前端开发体验。它主要由两部分组成&#xff1a; 一个开发服务器&#xff0c;它基于原生 ES 模块提供了丰富的内建功能&#xff0c;如速度快到惊人的模块热更新&#xff08;HMR&#xff09;。 …

如何监控特权帐户,保护敏感数据

IT基础设施的增长导致员工可以访问的凭据和资源数量急剧增加。每个组织都存储关键信息&#xff0c;这些信息构成了做出关键业务决策的基石。与特权用户共享这些数据可以授予他们访问普通员工没有的凭据的权限。如果特权帐户凭证落入不法分子之手&#xff0c;它们可能被滥用&…

【随笔】Git 高级篇 -- 分离 HEAD(十一)

&#x1f48c; 所属专栏&#xff1a;【Git】 &#x1f600; 作  者&#xff1a;我是夜阑的狗&#x1f436; &#x1f680; 个人简介&#xff1a;一个正在努力学技术的CV工程师&#xff0c;专注基础和实战分享 &#xff0c;欢迎咨询&#xff01; &#x1f496; 欢迎大…

成都直播基地出租:天府新区兴隆湖天府锋巢直播产业基地

天府新区兴隆湖天府锋巢直播产业基地&#xff0c;作为成都乃至西部地区的一颗璀璨明珠&#xff0c;正以其独特的魅力和无限的潜力&#xff0c;吸引着越来越多的目光。这里不仅是成都直播产业的聚集地&#xff0c;更是传统企业转型升级的摇篮&#xff0c;是新媒体时代下的创新高…

v-text 和v-html

接下来&#xff0c;我讲介绍一下v-text和v-html的使用方式以及它们之间的区别。 使用方法 <!DOCTYPE html> <html lang"en"><head><meta charset"UTF-8" /><meta name"viewport" content"widthdevice-widt…

2024 ccfcsp认证打卡 2022 09 01 如此编码

2022 09 01 如此编码 题解1题解2 题解1 import java.util.Scanner;public class Main {public static void main(String[] args) {Scanner sc new Scanner(System.in);int n sc.nextInt(); // 天数int m sc.nextInt(); // 科目数int[] b new int[n 1]; // 存放结果的数…

【零基础学数据结构】顺序表

目录 1.了解数据结构 什么是数据结构&#xff1f; 为什么要进行数据管理&#xff1f; 2.顺序表 顺序表概要解析&#xff1a; ​编辑顺序表的分类&#xff1a; 差别和使用优先度&#xff1a; 1.创建顺序表 1.1顺序表分为静态顺序表和动态顺序表 1.2顺序表的初始化…

北方经贸经济类知网收录月刊投稿发表论文

《北方经贸》期刊是由国家新闻出版总署批准&#xff0c;黑龙江省教育厅主管&#xff0c;黑龙江省经济管理干部学院主办的经济类综合期刊。期刊融理论性、知识性、实践性于一体&#xff0c;立足龙江&#xff0c;辐射全国&#xff0c;面向世界&#xff0c;注重研究解决重大现实理…

安泰电子 :电压放大器的技术指标有哪些

电压放大器是电子设备中常见的一种电路&#xff0c;它的作用是将输入信号的电压放大到所需的输出电压。电压放大器的技术指标描述了其性能和特征&#xff0c;涵盖了许多方面。下面西安安泰将详细介绍一些电压放大器的技术指标。 增益&#xff1a;增益是电压放大器最基本的指标之…

百卓Smart管理平台 importexport.php SQL注入漏洞复现(CVE-2024-27718)

0x01 产品简介 百卓Smart管理平台是北京百卓网络技术有限公司(以下简称百卓网络)的一款安全网关产品,是一家致力于构建下一代安全互联网的高科技企业。 0x02 漏洞概述 百卓Smart管理平台 importexport.php 接口处存在SQL注入漏洞,攻击者除了可以利用 SQL 注入漏洞获取数据…

简单了解波 Mono-repo Multi-repo(Poly-repo)

Mono-repo 和 Multi-repo 是软件开发中代码管理的两个不同策略。Mono-repo & Multi-repo 孰优孰劣是个老生常谈得话题了&#xff0c;这里就不 PK 了&#xff0c;“略微”看下两者区别。 当我们使用 Git 作为版本控制系统管理项目的代码时&#xff0c;那么 monorepo 与 mul…

【Java】Thread详解

&#x1f352;前言 本文将从以下几方面来展开对Thread的介绍。 1.线程创建 2.线程中断 3.线程等待 4.线程休眠 在前面的文章中&#xff0c;已经总结了关于Thread的一些理解。 在阅读本文之前&#xff0c;最好对其有一些基础的了解。 文章链接: 【JavaSE】进程是什么&#xff1f…

Webpack部署本地服务器

Webpack部署本地服务器 目录 Webpack部署本地服务器目的认识模块热替换&#xff08;HMR&#xff09;什么是 HMRHMR 通过如下几种方式, 来提高开发的速度如何使用 HMRhost 配置 目的 完成自动编译 常用方式: webpack-dev-server webpack-dev-server 是一个用于开发环境的 Web 服…

一文读懂!企业怎样才能选择适合自己的生产管理系统?

怎么选择适合所在企业的生产管理系统呢&#xff1f;该从哪些方面对生产管理系统进行评估&#xff1f;又怎样实现高效的生产管理呢&#xff1f; 本文我将和大家一起解决这些有关生产管理系统的问题&#xff1f; 生产管理系统模板&#xff0c;可直接查看和使用&#xff1a;https…