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

【左神算法刷题班】第18节:汉诺塔问题、岛屿问题、最大路径和问题

第18节

题目1:汉诺塔问题(变体)

体系学习班18节有讲暴力递归的汉诺塔原题。

给定一个数组arr,长度为N,arr中的值只有1,2,3三种

arr[i] == 1,代表汉诺塔问题中,从上往下第i个圆盘目前在左

arr[i] == 2,代表汉诺塔问题中,从上往下第i个圆盘目前在中

arr[i] == 3,代表汉诺塔问题中,从上往下第i个圆盘目前在右

那么arr整体就代表汉诺塔游戏过程中的一个状况

如果这个状况不是汉诺塔最优解运动过程中的状况,返回-1

如果这个状况是汉诺塔最优解运动过程中的状况,返回它是第几个状况(而不是还剩几个状况)

思路

对于传统的汉诺塔问题,如果我要将 123456 从最左边的柱子上移动到最右边的柱子上,需要分成三大步:

  1. 【第一大步】将 12345 从左边的柱子移动到中间的位置
  2. 【第二大步】将 6 从左边的柱子移动到右边的位置
  3. 【第三大步】将 12345 从中间的位置移动到右边的位置

上述传统问题的解法是,定义递归函数 f(i, from, to, other),表示将 [0~i] 的圆盘从 from 柱子移动到 to 柱子上,另外那个柱子叫 other。

对于本题,需要明确一下题意,有几个已知条件:

  1. 汉诺塔问题,最优解是唯一的路径。
  2. 题目中给的过程状态,如果不在唯一路径上,就返回-1。
  3. 举个极端的例子,1层汉诺塔问题,把1从最左边的柱子上移动到最右边的柱子上,只要一步就可以了。而”1在中间这个柱子上“这个状态,就是一个不在最优解路径上的例子。

本题的解法是,定义递归函数int step(int[] arr, int i, int from, int to, int other),表示当前来到 arr 状态下,将 [0~i] 的圆盘从 from 柱子移动到 to 柱子上,另外那个柱子叫 other,返回至少需要几步。

public static int kth(int[] arr) {int N = arr.length;return step(arr, N - 1, 1, 3, 2);
}// 我的疑问:arr为什么全程不更新?
// 自问自答:因为返回它当前走到了第几个状况,而不是还剩几个状况。
public static int step(int[] arr, int index, int from, int to, int other) {if (index == -1) {return 0;}if (arr[index] == other) { // 最大的数字只可能在from或者to的底部,不可能在other上return -1;}// arr[index]的值,剩下两种情况:// 情况1:arr[index] == from// 情况2:arr[index] == toif (arr[index] == from) { // 情况1:如果index号圆盘还在from上,说明上述连【第一大步】都没走完// 因为我只想知道当前已经走过多少步了,所以只要统计在【第一大步】中走了多少步就可以了,后面的【第二大步】【第三大步】肯定根本没走// 怎么统计呢?我们知道【第一大步】的目标是将[0~i-1]从from挪到other上,而且当前已经走到arr状态了,所以就这样继续递归return step(arr, index - 1, from, other, to);} else { // 情况2:如果index号圆盘已经在to上了,说明已经完成[0~index-1]的汉诺塔问题了// 【第一大步】已经完成的从[0~index-1]范围上的index层汉诺塔问题需要的步骤数(n层汉诺塔,最优解2^n-1步)int p1 = (1 << index) - 1; // 【第二大步】已经将index号圆盘从from挪到to了,因为我们从arr中看到index号圆盘已经在to上了int p2 = 1; // 【第三大步】当前正在经历的,将[0~i-1]号圆盘从other挪到to上,在arr状态下,统计已经走过多少步了?int p3 = step(arr, index - 1, other, to, from); // 如果发现它的子问题根本就不是最优解的某一步,直接返回-1if (p3 == -1) { return -1;}return p1 + p2 + p3;}
}
image-20230814002726237

题目2:两个岛屿的距离,“感染”问题

Leetcode 原题:

https://leetcode.com/problems/shortest-bridge/

我在力扣上的自己写的答案:

class Solution {int m, n;public static final int offset = 100;public int shortestBridge(int[][] grid) {m = grid.length;n = grid[0].length;// 将其中一个岛A加offset,用来区分两个岛label:for (int i = 0; i < m; i++) {for (int j = 0; j < n; j++) {if (grid[i][j] == 1) {incr(grid, i, j);break label; // 中断所有循环,回到label处,但并不重新进入循环}}}// 左上角主动感染,右下角原地不动int term = offset;while (true) {boolean[][] seen = new boolean[m][n];for (int i = 0; i < m; i++) {for (int j = 0; j < n; j++) {if (grid[i][j] == term && !seen[i][j]) {int result = process(grid, i, j, term, seen);if (result != Integer.MAX_VALUE) return result - offset;}}}term++;}}// 当前岛屿向外感染public int process(int[][] grid, int i, int j, int term, boolean[][] seen) {int result = Integer.MAX_VALUE;if (i < 0 || i == m || j < 0 || j == n || seen[i][j]) return result; // 越界,或重复路线seen[i][j] = true;if (grid[i][j] == 0) { // 当前位置未感染,则感染grid[i][j] = term + 1;} else if (grid[i][j] == term) { // 当前位置是感染源,则去感染周围result = Math.min(result, process(grid, i + 1, j, term, seen));result = Math.min(result, process(grid, i - 1, j, term, seen));result = Math.min(result, process(grid, i, j + 1, term, seen));result = Math.min(result, process(grid, i, j - 1, term, seen));} else if (grid[i][j] == 1) { // 两岛接壤,则快速返回return term;}return result;}// 给其中一个岛加offsetpublic void incr(int[][] grid, int i, int j) {if (i < 0 || i == m || j < 0 || j == n) return;if (grid[i][j] == 1) {grid[i][j] = offset;incr(grid, i + 1, j);incr(grid, i - 1, j);incr(grid, i, j + 1);incr(grid, i, j - 1);}}
}

题目3:最大路径和

牛客网原题:

https://www.nowcoder.com/questionTerminal/8ecfe02124674e908b2aae65aad4efdf

给定一个矩阵matrix,先从左上角开始,每一步只能往右或者往下走,走到右下角。然后从右下角出发,每一步只能往上或者往左走,再回到左上角。任何一个位置的数字,只能获得一遍。返回最大路径和。

输入描述
第一行输入两个整数M和N,M,N<=200
接下来M行,每行N个整数,表示矩阵中元素5 10
1 1 1 1 1 0 0 0 0 0
0 0 0 0 1 0 0 0 0 0
0 0 0 0 1 0 0 0 0 1
1 0 0 0 1 0 0 0 0 0
0 0 0 0 1 1 1 1 1 1
输出描述
输出一个整数,表示最大路径和16
思路

第一次见到这题,是在体系学习班第14节。当时只讲了不能贪心,应该用dp,但没有细说。

黄色部分表示我想要拿到的位置:

在这里插入图片描述

错误的贪心路径

少拿一个灰色的格子。
在这里插入图片描述

正确的路径

最好情况下,能够拿到所有的格子。

在这里插入图片描述

虽然题目要求是一来一回,但我们可以想象成有两个人 a、b,都从左上角走到右下角,求整个过程中,最多能拿到多少值。

内存超限版本如下。其实可以省掉一个维度就不会超了,因为(i1, j1), (i2, j2) 两个坐标中,存在关系:i1+j1=i2+j2。可变参数数量能省则省!

import java.util.Scanner;// 注意类名必须为 Main, 不要有任何 package xxx 信息
public class Main {static int[][] arr;public static void main(String[] args) {Scanner in = new Scanner(System.in);int m = in.nextInt();int n = in.nextInt();arr = new int[m][n];for (int i = 0; i < m; i++) {for (int j = 0; j < n; j++) {arr[i][j] = in.nextInt();}}int[][][][] dp = new int[m][n][m][n];for (int i = 0; i < m; i++) {for (int j = 0; j < n; j++) {for (int k = 0; k < m; k++) {for (int l = 0; l < n; l++) {dp[i][j][k][l] = -1;}}}}int res = process(0, 0, 0, 0, dp);System.out.println(res);}// 当前a在i1,j1位置,b在i2,j2位置// 两个人都只能向右走或者向下走,求能拿到的最多点数public static int process(int i1, int j1, int i2, int j2, int[][][][] dp) {if (i1 == arr.length || j1 == arr[0].length) return 0;if (i2 == arr.length || j2 == arr[0].length) return 0;if (dp[i1][j1][i2][j2] >= 0) return dp[i1][j1][i2][j2];// a,b如果走到了同一个位置,点数只能累加一次int res = arr[i1][j1];if (i1 != i2 && j1 != j2) res += arr[i2][j2];// a向右,b向右int p1 = process(i1 + 1, j1, i2 + 1, j2, dp);// a向下,b向下int p2 = process(i1, j1 + 1, i2, j2 + 1, dp);// a向右,b向下int p3 = process(i1, j1 + 1, i2 + 1, j2, dp);// a向下,b向右int p4 = process(i1 + 1, j1, i2, j2 + 1, dp);res += Math.max(Math.max(p1, p2), Math.max(p3, p4));dp[i1][j1][i2][j2] = res;return res;}
}
/*5 10
1 1 1 1 1 0 0 0 0 0
0 0 0 0 1 0 0 0 0 0
0 0 0 0 1 0 0 0 0 1
1 0 0 0 1 0 0 0 0 0
0 0 0 0 1 1 1 1 1 12 2
1 1
1 1*/

题目4

牛客网原题:

https://www.nowcoder.com/practice/7201cacf73e7495aa5f88b223bbbf6d1

给定两个有序数组arr1和arr2,再给定一个整数k,你可以从来自arr1和arr2的两个数各选一个数,返回相加和最大的前k个。

思路

不能用双指针从最右边开始往左滑动,因为这样会丢失本来可以重复使用的数字。

正确的方法是用大根堆。

当从大根堆拿走一个元素之后,将表格中在它左边和上边的元素,加入大根堆。

在这里插入图片描述

相关文章:

【左神算法刷题班】第18节:汉诺塔问题、岛屿问题、最大路径和问题

第18节 题目1&#xff1a;汉诺塔问题&#xff08;变体&#xff09; 体系学习班18节有讲暴力递归的汉诺塔原题。 给定一个数组arr&#xff0c;长度为N&#xff0c;arr中的值只有1&#xff0c;2&#xff0c;3三种 arr[i] 1&#xff0c;代表汉诺塔问题中&#xff0c;从上往下第…...

网络安全体系架构介绍

网络安全体系是一项复杂的系统工程&#xff0c;需要把安全组织体系、安全技术体系和安全管理体系等手段进行有机融合&#xff0c;构建一体化的整体安全屏障。针对网络安全防护&#xff0c;美国曾提出多个网络安全体系模型和架构&#xff0c;其中比较经典的包括PDRR模型、P2DR模…...

JSP实训项目设计报告—MVC简易购物商城

JSP实训项目设计报告—MVC简易购物商城 文章目录 JSP实训项目设计报告—MVC简易购物商城设计目的设计要求设计思路系统要求单点登录模块商品展示模块购物车展示模块 概要设计Model层View层Controller层 详细设计Model层View层登录界面系统主界面 Controller层 系统运行效果项目…...

41、可靠传输——停等ARQ

前面两节内容我们学习了传输层的基本概况的一些知识&#xff0c;包括传输层在TCP/IP协议栈中负责的任务、传输层的两大协议&#xff0c;以及端口号、套接字等一些基本的概念。从这一节开始&#xff0c;我们将开启两大协议中TCP协议的学习。 但是&#xff0c;经过之前的学习&am…...

RK3568 cmake编译

一.简介 CMake是开源、跨平台的构建工具&#xff0c;可以让我们通过编写简单的配置文件去生成本地的Makefile&#xff0c;这个配置文件是独立于运行平台和编译器的&#xff0c;这样就不用亲自去编写Makefile了&#xff0c;而且配置文件可以直接拿到其它平台上使用&#xff0c;…...

详细安装配置django

安装配置使用Django。 1&#xff0c;下载安装 django pip install django 2.创建设置项目 先进入要放置项目的文件夹下 2.1&#xff0c; 创建项目 django-admin startproject Api_project 2.2&#xff0c; 创建app命令 cd Api_project dir看一下是否有 manage.py 文件…...

HTTP之cookie基础学习

目录 Cookie 什么是Cookie Cookie分类 Cookie版本 Cookie工作原理 Cookie详解 创建cookie cookie编码 cookie过期时间选项 Cookie流程 Cookie使用 会话管理 个性化信息 记录用户的行为 Cookie属性 domain选项 path选项 secure选项 cookie…...

观察者模式和发布订阅模式

观察者模式与发布订阅模式的区别&#xff1a; 1、观察者模式中只有观察者和被观察者&#xff0c;发布订阅模式中有发布者、订阅者、调度中心 2、观察者模式是被观察者发生变化时自己通知观察者&#xff0c;发布订阅模式是通过调度中心来进行分布订阅操作 发布订阅模式 class …...

利用ViewModel和LiveData进行数据管理

利用ViewModel和LiveData进行数据管理 1. 引言 在当今移动应用开发的世界中&#xff0c;数据管理是一个至关重要的方面。随着应用的复杂性不断增加&#xff0c;需要有效地管理和维护应用中的数据。无论是从服务器获取数据、本地数据库存储还是用户界面的状态&#xff0c;数据…...

前后端分离------后端创建笔记(05)用户列表查询接口(下)

本文章转载于【SpringBootVue】全网最简单但实用的前后端分离项目实战笔记 - 前端_大菜007的博客-CSDN博客 仅用于学习和讨论&#xff0c;如有侵权请联系 源码&#xff1a;https://gitee.com/green_vegetables/x-admin-project.git 素材&#xff1a;https://pan.baidu.com/s/…...

浅谈GIS和三维GIS的区别?

GIS&#xff08;地理信息系统&#xff09;和三维GIS&#xff08;3D地理信息系统&#xff09;是地理信息领域的两个重要概念&#xff0c;它们在地理数据的处理和分析方面具有不同的特点和应用。可能很多人分不清二者的区别&#xff0c;本文就带大家简单了解一下二者的区别。 定义…...

ArcGIS Maps SDK for JavaScript系列之三:在Vue3中使用ArcGIS API加载三维地球

目录 SceneView类的常用属性SceneView类的常用方法vue3中使用SceneView类创建三维地球项目准备引入ArcGIS API创建Vue组件在OnMounted中调用初始化函数initArcGisMap创建Camera对象Camera的常用属性Camera的常用方法 要在Vue 3中使用ArcGIS API for JavaScript加载和展示三维地…...

设计列表和超链接

在网页中&#xff0c;大部分信息都是列表结构&#xff0c;如菜单栏、图文列表、分类导航、新闻列表、栏目列表等。HTML5定义了一套列表标签&#xff0c;通过列表结构实现对网页信息的合理排版。另外&#xff0c;网页中还包含大量超链接&#xff0c;通过它实现网页、位置的跳转&…...

rust包跨平台编译,macbook ,linux

在 MacBook 上编译 Rust 项目并生成 Linux 包需要一些步骤。以下是一般的步骤概述&#xff1a; 1. **安装所需工具&#xff1a;** 首先&#xff0c;确保您的 MacBook 上已经安装了所需的工具。您需要 Rust 编程语言的工具链以及一些用于交叉编译到 Linux 的工具。 - 安装 R…...

JAVA集合-List

// 数组的缺点&#xff1a;每次使用都需要指定长度&#xff0c;掉率低&#xff0c;操作麻烦 // // 【java集合体系】&#xff1a;分类&#xff1a;6个接口&#xff0c;1个工具类 // 6个接口&#xff1a; 单列 :Collection,(父接口) // …...

Python|OpenCV-绘制图形和添加文字的方法(2)

前言 本文是该专栏的第2篇,后面将持续分享OpenCV计算机视觉的干货知识,记得关注。 OpenCV作为一个强大的计算机视觉功能库,除了能解决图像处理和计算机视觉任务之外,它还有着非常丰富的图像绘制功能。可以说,不论是在计算机视觉任务中标记目标领域,还是在图像上绘制一些…...

使用GO编译wasm文件并在nodejs中使用

使用GO编译wasm文件并在nodejs中使用 安装Go相关环境 # 安装GO # mac使用homebrew安装 /bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)" brew install go# vi &#xff5e;/.bashrc&#xff0c; 添加如下内容 e…...

BM22 比较版本号

一.双指针遍历截取 import java.util.*;public class Solution {/*** 代码中的类名、方法名、参数名已经指定&#xff0c;请勿修改&#xff0c;直接返回方法规定的值即可** 比较版本号* param version1 string字符串 * param version2 string字符串 * return int整型*/public …...

【Java】Maven配置文件帮助文档(settings.xml 和 pom.xml)

文章目录 1. settings.xml1.1 localRepository1.2 interactiveMode1.3 offline1.4 pluginGroups1.5 proxies1.6 servers1.7 mirrors1.8 profiles1.9 activeProfiles 2. pom.xml2.1 本项目信息2.2 父项目信息2.3 prerequisites2.4 issueManagement2.5 ciManagement2.6 inception…...

人脸识别技术应用安全管理规定(试行)

近年来&#xff0c;人脸识别技术不断成熟&#xff0c;已大量应用于治安管理、金融支付、门禁考勤等诸多领域&#xff0c;极大便捷了公众生活。然而&#xff0c;人脸识别技术在得到广泛应用的同时&#xff0c;仍存在一些不规范现象。人脸识别因其技术特点&#xff0c;涉及公众敏…...

Golang 面试经典题:map 的 key 可以是什么类型?哪些不可以?

Golang 面试经典题&#xff1a;map 的 key 可以是什么类型&#xff1f;哪些不可以&#xff1f; 在 Golang 的面试中&#xff0c;map 类型的使用是一个常见的考点&#xff0c;其中对 key 类型的合法性 是一道常被提及的基础却很容易被忽视的问题。本文将带你深入理解 Golang 中…...

iPhone密码忘记了办?iPhoneUnlocker,iPhone解锁工具Aiseesoft iPhone Unlocker 高级注册版​分享

平时用 iPhone 的时候&#xff0c;难免会碰到解锁的麻烦事。比如密码忘了、人脸识别 / 指纹识别突然不灵&#xff0c;或者买了二手 iPhone 却被原来的 iCloud 账号锁住&#xff0c;这时候就需要靠谱的解锁工具来帮忙了。Aiseesoft iPhone Unlocker 就是专门解决这些问题的软件&…...

【磁盘】每天掌握一个Linux命令 - iostat

目录 【磁盘】每天掌握一个Linux命令 - iostat工具概述安装方式核心功能基础用法进阶操作实战案例面试题场景生产场景 注意事项 【磁盘】每天掌握一个Linux命令 - iostat 工具概述 iostat&#xff08;I/O Statistics&#xff09;是Linux系统下用于监视系统输入输出设备和CPU使…...

生成 Git SSH 证书

&#x1f511; 1. ​​生成 SSH 密钥对​​ 在终端&#xff08;Windows 使用 Git Bash&#xff0c;Mac/Linux 使用 Terminal&#xff09;执行命令&#xff1a; ssh-keygen -t rsa -b 4096 -C "your_emailexample.com" ​​参数说明​​&#xff1a; -t rsa&#x…...

鸿蒙中用HarmonyOS SDK应用服务 HarmonyOS5开发一个医院查看报告小程序

一、开发环境准备 ​​工具安装​​&#xff1a; 下载安装DevEco Studio 4.0&#xff08;支持HarmonyOS 5&#xff09;配置HarmonyOS SDK 5.0确保Node.js版本≥14 ​​项目初始化​​&#xff1a; ohpm init harmony/hospital-report-app 二、核心功能模块实现 1. 报告列表…...

CocosCreator 之 JavaScript/TypeScript和Java的相互交互

引擎版本&#xff1a; 3.8.1 语言&#xff1a; JavaScript/TypeScript、C、Java 环境&#xff1a;Window 参考&#xff1a;Java原生反射机制 您好&#xff0c;我是鹤九日&#xff01; 回顾 在上篇文章中&#xff1a;CocosCreator Android项目接入UnityAds 广告SDK。 我们简单讲…...

从零实现STL哈希容器:unordered_map/unordered_set封装详解

本篇文章是对C学习的STL哈希容器自主实现部分的学习分享 希望也能为你带来些帮助~ 那咱们废话不多说&#xff0c;直接开始吧&#xff01; 一、源码结构分析 1. SGISTL30实现剖析 // hash_set核心结构 template <class Value, class HashFcn, ...> class hash_set {ty…...

uniapp微信小程序视频实时流+pc端预览方案

方案类型技术实现是否免费优点缺点适用场景延迟范围开发复杂度​WebSocket图片帧​定时拍照Base64传输✅ 完全免费无需服务器 纯前端实现高延迟高流量 帧率极低个人demo测试 超低频监控500ms-2s⭐⭐​RTMP推流​TRTC/即构SDK推流❌ 付费方案 &#xff08;部分有免费额度&#x…...

Ascend NPU上适配Step-Audio模型

1 概述 1.1 简述 Step-Audio 是业界首个集语音理解与生成控制一体化的产品级开源实时语音对话系统&#xff0c;支持多语言对话&#xff08;如 中文&#xff0c;英文&#xff0c;日语&#xff09;&#xff0c;语音情感&#xff08;如 开心&#xff0c;悲伤&#xff09;&#x…...

数据库分批入库

今天在工作中&#xff0c;遇到一个问题&#xff0c;就是分批查询的时候&#xff0c;由于批次过大导致出现了一些问题&#xff0c;一下是问题描述和解决方案&#xff1a; 示例&#xff1a; // 假设已有数据列表 dataList 和 PreparedStatement pstmt int batchSize 1000; // …...