第三十九天| 62.不同路徑、63. 不同路徑 II

Leetcode?62.不同路徑

題目鏈接:62 不同路徑

題干:一個機器人位于一個?m x n?網格的左上角 (起始點在下圖中標記為 “Start” )。

機器人每次只能向下或者向右移動一步。機器人試圖達到網格的右下角(在下圖中標記為 “Finish” )。問總共有多少條不同的路徑?

思考一:動態規劃。

  • 確定dp數組(dp table)以及下標的含義

dp[i][j] :表示從(0 ,0)出發,到(i, j) 有dp[i][j]條不同的路徑。

  • 確定遞推公式

從dp[i][j]的定義可以看出,只能有兩個方向來推導出來,即dp[i - 1][j]向右走 和 dp[i][j - 1]向下走。

所以dp[i][j] = dp[i - 1][j] + dp[i][j - 1]。

  • dp數組的初始化

首先dp[i][0]一定都是1,因為從(0, 0)的位置到(i, 0)的路徑只有一條,dp[0][j]也同理。代碼如下:

for (int i = 0; i < m; i++) dp[i][0] = 1;
for (int j = 0; j < n; j++) dp[0][j] = 1;
  • 確定遍歷順序

從遞歸公式dp[i][j] = dp[i - 1][j] + dp[i][j - 1];中可以看出,dp[i][j]是依賴 dp[i - 1][j]和 dp[i][j - 1],那么遍歷的順序一定是從左到右一層一層遍歷的。

  • 舉例推導dp數組

代碼:

class Solution {
public:int uniquePaths(int m, int n) {int dp[m][n];       //記錄到達下標(i,j)的路徑數//初始化for (int i = 0; i < m; i++)     //從起始點一直到最右邊只存在一條路徑dp[i][0] = 1;for (int j = 0; j < n; j++)     //從起始點一直到最下邊只存在一條路徑dp[0][j] = 1;for (int i = 1; i < m; i++) {for (int j = 1; j < n; j++)dp[i][j] = dp[i - 1][j] + dp[i][j - 1];     //遞推公式}return dp[m - 1][n - 1];}
};

優化:其實用一個一維數組(可以理解是滾動數組)即可,可以優化空間。

代碼:

class Solution {
public:int uniquePaths(int m, int n) {vector<int> dp(n);for (int i = 0; i < n; i++) dp[i] = 1;        //初始化for (int j = 1; j < m; j++) {for (int i = 1; i < n; i++) {        //處理每列元素dp[i] += dp[i - 1];}}return dp[n - 1];}
};

思考二:深度優先搜索。題目中說機器人每次只能向下或者向右移動一步,那么其實機器人走過的路徑可以抽象為一棵二叉樹,而葉子節點就是終點!如圖:

但如果只是按以上思路同一位置多次計算,會超時。因此要加上備忘錄,初始化為-1。終止條件加上判斷當前位置備忘錄是否記錄過,記錄過則直接返回數據。單層遞歸處理邏輯也要記錄數據。?

代碼:

class Solution {
public:vector<vector<int>> memo;       //添加備忘錄int dfs(int row, int col, const int m, const int n) {if (row > m || col > n) return 0;       //超出邊界返回0if (row == m && col == n)   return 1;   //搜索到一條路徑if (memo[row][col] != -1)   return memo[row][col];      //訪問過則直接返回記錄值int right = dfs(row + 1, col, m, n);        //向右移動int down = dfs(row, col + 1, m, n);         //向下移動memo[row][col] = right + down;      //記錄數據return memo[row][col];  }int uniquePaths(int m, int n) {if (m < 1 || n < 1) return 0;memo = vector<vector<int>>(m + 1, vector<int>(n + 1, -1));return dfs(1, 1, m, n);}
};

思考三:數論法。

在下圖中,可以看出一共m,n的話,無論怎么走,走到終點都需要 m + n - 2 步。

在這m + n - 2 步中,一定有 m - 1 步是要向下走的,不用管什么時候向下走。

那么路徑問題就轉換為,給你m + n - 2個不同的數,隨便取m - 1(或n - 1)個數,有幾種取法。

這便是組合問題。答案為_{m+n-2}^{m-1}\textrm{C}_{m + n -2}^{n -1}\textrm{C},取較小值計算。

求組合要防止兩個int相乘溢出。?所以不能把算式的分子都算出來,分母都算出來再做除法。

代碼:

class Solution {
public:int uniquePaths(int m, int n) {long long numerator = 1;       //分子int denominator = 1;           //分母int count = m > n ? n - 1 : m - 1;int num = m + n - 2;while (count > 0) {     //邊乘邊除numerator *= num;denominator *= count;if (denominator != 1 && numerator % denominator == 0) {     //可整除numerator /= denominator;denominator = 1;}num--;count--;}return numerator;}
};

Leetcode?63. 不同路徑 II

題目鏈接:63 不同路徑 II

題干:一個機器人位于一個?m x n?網格的左上角 (起始點在下圖中標記為 “Start” )。

機器人每次只能向下或者向右移動一步。機器人試圖達到網格的右下角(在下圖中標記為 “Finish”)。

現在考慮網格中有障礙物。那么從左上角到右下角將會有多少條不同的路徑?

網格中的障礙物和空位置分別用?1?和?0?來表示。

思考一:動態規劃。

和上題的區別僅在障礙物,因此思路僅在確定遞推公式dp數組的初始化兩步存在差異

  • 確定遞推公式

從dp[i][j]的定義可以看出,只能有兩個方向來推導出來,即dp[i - 1][j]向右走 和 dp[i][j - 1]向下走。

正常公式應為dp[i][j] = dp[i - 1][j] + dp[i][j - 1]。

但障礙物所在位置不可達,因此在處理前先判斷。代碼如下:

if (obstacleGrid[i][j] == 1)        //此下標位置存在障礙物    continue;       
  • dp數組的初始化

由于障礙物的存在,因此只有在未碰到障礙物的前面位置dp[i][0]=1。dp[0][j]也同理。代碼如下:

for (int i = 0; i < m && obstacleGrid[i][0] == 0; i++)     //從起始點向右直到碰到邊界或者障礙物只存在一條路徑dp[i][0] = 1;
for (int j = 0; j < n && obstacleGrid[0][j] == 0; j++)     //從起始點向下直到碰到邊界或者障礙物只存在一條路徑dp[0][j] = 1;

代碼:

class Solution {
public:int uniquePathsWithObstacles(vector<vector<int>>& obstacleGrid) {int m = obstacleGrid.size();int n = obstacleGrid[0].size();if (obstacleGrid[m - 1][n - 1] == 1 || obstacleGrid[0][0] == 1) //如果在起點或終點出現了障礙直接返回0return 0;vector<vector<int>> dp(m, vector<int>(n, 0));       //記錄到達下標(i,j)的路徑數   //初始化for (int i = 0; i < m && obstacleGrid[i][0] == 0; i++)     //從起始點向右直到碰到邊界或者障礙物只存在一條路徑dp[i][0] = 1;for (int j = 0; j < n && obstacleGrid[0][j] == 0; j++)     //從起始點向下直到碰到邊界或者障礙物只存在一條路徑dp[0][j] = 1;for (int i = 1; i < m; i++) {for (int j = 1; j < n; j++) {if (obstacleGrid[i][j] == 1)    continue;       //此下標位置存在障礙物dp[i][j] = dp[i - 1][j] + dp[i][j - 1];     //遞推公式}}return dp[m - 1][n - 1];}
};

思考二:深度優先搜索。僅在終止條件這多加碰到障礙物則此條路徑作廢返回0即可。當然還得加上備忘錄減少處理時間。

代碼:

class Solution {
public:vector<vector<int>> memo;       //添加備忘錄int dfs(int row, int col, const int m, const int n, const vector<vector<int>>& obstacleGrid) {if (row > m - 1 || col > n - 1) return 0;       //超出邊界返回0if (obstacleGrid[row][col] == 1)    return 0;       //碰到障礙物返回0if (row == m - 1 && col == n - 1)   return 1;       //搜索到一條路徑if (memo[row][col] != -1)   return memo[row][col];      //訪問過則直接返回記錄值int right = dfs(row + 1, col, m, n, obstacleGrid);      //向右int down = dfs(row, col + 1, m, n, obstacleGrid);       //向下memo[row][col] = right + down;      //記錄數據return memo[row][col];}int uniquePathsWithObstacles(vector<vector<int>>& obstacleGrid) {int m = obstacleGrid.size();int n = obstacleGrid[0].size();memo = vector<vector<int>>(m, vector<int>(n, -1));if (m < 1 || n < 1) return 0;return dfs(0, 0, m, n, obstacleGrid);}
};

自我總結:

  • 了解到C++備忘錄模式,減少處理時間。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/696290.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/696290.shtml
英文地址,請注明出處:http://en.pswp.cn/news/696290.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

c#之列表

// List<int> scoreList new List<int>();//創建空列表var scoreListnew List<int>();//匿名方式創建scoreList.Add(912);//插入數據scoreList.Add(45);scoreList.Add(415);scoreList.Add(452);scoreList.Add(4451);scoreList.Add(245);scoreList.Add(445);…

十六、多邊形填充和繪制

項目功能實現&#xff1a;對多邊形進行輪廓繪制和填充 按照之前的博文結構來&#xff0c;這里就不在贅述了 一、頭文件 mult-drawing.h #pragma once#include<opencv2/opencv.hpp>using namespace cv;class Mult_Drawing { public:void mult_drawing(); };#pragma onc…

vue如何動態加載顯示本地圖片資源

在實際開發中&#xff0c;根據某一個變量動態展示圖片的情況有很多。實現方法分打包構建工具的差異而不同。 1、webpack的項目 require引入圖片資源 2、vite的項目 new URL(url,base).href 疑問解答&#xff1a;為什么vite項目不可以用require&#xff1f; 原因在于&#xf…

Elastic Stack--01--簡介、安裝

提示&#xff1a;文章寫完后&#xff0c;目錄可以自動生成&#xff0c;如何生成可參考右邊的幫助文檔 文章目錄 1. Elastic Stack 簡介為什么要學習ESDB-Engines搜索引擎類數據庫排名常年霸榜![在這里插入圖片描述](https://img-blog.csdnimg.cn/direct/051342a83f574c8c910cda…

微信小程序獨立分包與分包預下載

官網鏈接 獨立分包配置方法 獨立分包使用限制 獨立分包中不能依賴主包和其他分包中的內容&#xff0c;包括 js 文件、模板、wxss、自定義組件等&#xff1b;App 只能在主包內定義&#xff0c;獨立分包中不能定義 App&#xff0c;會造成無法預期的行為獨立分包中暫時不支持使用…

cocos creator3.x項目打包成aar 加入到已有的Android工程

Cocos crearor版本&#xff1a; 3.4.2 Android Studio Flamingo | 2022.2.1 Patch 2 1、配置構建安卓項目 2、 運行編譯無報錯 出現問題可嘗試修改Gradle版本 修改jdk版本 3、對libservice打包成aar 打包完后 再build/outputs找到aar 如果看不到Tasks模塊&#xff0c;在Fil…

sqlserver觸發器

在SQL Server中&#xff0c;觸發器是一種特殊的數據庫對象&#xff0c;它們會在表上執行特定的操作時自動觸發。觸發器可以用于在表上插入、更新或刪除數據時執行自定義的邏輯。觸發器通常用于實施數據完整性約束、審計和日志記錄等操作。 觸發器有三種主要類型&#xff1a; 插…

人機交互新研究:MIT開發了結合腦電和眼電的新式眼鏡,與機器狗交互

還記得之前的AI讀心術嗎&#xff1f;最近&#xff0c;「心想事成」的能力再次進化&#xff0c; ——人類可以通過自己的想法直接控制機器人了&#xff01; 來自麻省理工的研究人員發表了Ddog項目&#xff0c;通過自己開發的腦機接口&#xff08;BCI&#xff09;設備&#xff…

面試答疑03

1、登錄鑒權怎么做的&#xff1f;為什么采用jwt的方式&#xff1f;有什么好處&#xff1f; Java登錄鑒權常見的實現方式包括**CookieSession、HTTP Basic Authentication、ServletJDBC**等。 在Java的Web應用中&#xff0c;登錄鑒權是確認用戶身份的關鍵環節。一個常用的傳統…

【Linux內核模塊加新功能 DAY6-8】

一、向內核添加新功能 1.1 靜態加載法&#xff1a; 即新功能源碼與內核其它代碼一起編譯進uImage文件內 新功能源碼與Linux內核源碼在同一目錄結構下在linux-3.14/driver/char/目錄下編寫myhello.c&#xff0c;文件內容如下&#xff1a;#include <linux/module.h> #inc…

Vue項目啟動過程全記錄(node.js運行環境搭建)

一、安裝node.js并配置環境變量 1、安裝node.js 從Node.js官網下載安裝包并安裝。然后在安裝后的目錄&#xff08;如果是下載的壓縮文件&#xff0c;則是解壓縮的目錄&#xff09;下新建node_global和node_cache這兩個文件夾。 node_global&#xff1a;npm全局安裝位置 node_…

Golang 中 NATS JetStream 的高級特性有哪些?

NATS JetStream 是 NATS 消息系統的一個高級功能模塊&#xff0c;提供了許多高級特性&#xff0c;使得它在處理消息時更加靈活、可靠和高效。以下是 NATS JetStream 的一些高級特性&#xff1a; 持久化消息存儲&#xff1a;NATS JetStream 使用持久化存儲引擎&#xff0c;可以確…

代碼隨想錄三刷day06

提示&#xff1a;文章寫完后&#xff0c;目錄可以自動生成&#xff0c;如何生成可參考右邊的幫助文檔 文章目錄 前言一、力扣203. 移除鏈表元素二、力扣707. 設計鏈表三、力扣 前言 遞歸法相對抽象一些&#xff0c;但是其實和雙指針法是一樣的邏輯&#xff0c;同樣是當cur為空的…

機器學習面試:邏輯回歸與樸素貝葉斯區別

邏輯回歸與樸素貝葉斯區別有以下幾個方面: (1)邏輯回歸是判別模型&#xff0c;樸素貝葉斯是生成模型&#xff0c;所以生成和判別的所有區別它們都有。 (2)樸素貝葉斯屬于貝葉斯&#xff0c;邏輯回歸是最大似然&#xff0c;兩種概率哲學間的區別。 (3)樸素貝葉斯需要條件獨立假設…

【刷題】牛客 JZ64 求1+2+3+...+n

刷題 題目描述思路一 &#xff08;暴力遞歸版&#xff09;思路二 &#xff08;妙用內存版&#xff09;思路三 &#xff08;快速乘法版&#xff09;思路四 &#xff08;構造巧解版&#xff09;Thanks?(&#xff65;ω&#xff65;)&#xff89;謝謝閱讀&#xff01;&#xff01…

力扣49.字母異位詞分組

題目描述&#xff1a; 49. 字母異位詞分組 難度 中等 給你一個字符串數組&#xff0c;請你將 字母異位詞 組合在一起。可以按任意順序返回結果列表。 字母異位詞 是由重新排列源單詞的所有字母得到的一個新單詞。 示例 1: 輸入: strs ["eat", "tea"…

在Linux中查找大文件

在Linux中查找大文件&#xff0c;你可以使用find命令結合其他工具&#xff08;如sort和du&#xff09;來實現。以下是一些常見的方法&#xff1a; 1. 使用find命令查找大文件 你可以使用find命令來查找特定大小以上的文件。例如&#xff0c;要查找當前目錄及其子目錄中大小超…

高盛:日本這輪通脹是否可持續,關鍵看房租

租金在日本CPI中的權重高達20%&#xff0c;高盛預計短期內租金將繼續拖累通脹至1.7%或以下&#xff0c;長期有望溫和上行&#xff0c;使通脹穩在2%的水平。 日本正在轉向“去通縮”&#xff0c;房租能否支撐通脹態勢&#xff1f; 在日股今年一路高歌、有望“收復失地”時&…

redis的AOF機制

Redis AOF(Append Only File)機制是為了記錄每一次redis命令的操作并用于恢復數據。 AOF按順序記錄每一步操作&#xff0c;例如&#xff1a; set k 3, set k 5, set k 10 &#xff0c;當服務器重啟后依次執行命令恢復k 10。 日志寫入有三種方式&#xff1a; Always&#x…

【【深入淺出的了解從算法到RTL的基本流程】】

深入淺出的了解從算法到RTL的基本流程 首先 明確需求 &#xff0c;明確題目 接下來是第一輪建模-------目的是 驗證算法的正確性 這個階段分為以下兩個方面 一方面是 &#xff1a; 通過一些算法仿真工具來對 這個設計進行建模 — 算法原理建模 第二方面是 &#xff1a; 是 算…