一、不同路径
题目:
一个机器人位于一个 m x n
网格的左上角 (起始点在下图中标记为 “Start” )。机器人每次只能向下或者向右移动一步。机器人试图达到网格的右下角(在下图中标记为 “Finish” )。问总共有多少条不同的路径?
思路:
这里需要用动态规划的方法思考,采用二维数组的方法,假设start位置为(0,0),二维数组为dp[m][n], 这里首先应该搞清楚,由于只能向右或向下移动,因此在第一行或者第一列移动时无论到什么位置,都只有一条路,因此可知 dp[0][n] 和 dp[m][0] 的值一定为1
这里的dp数组含义是记录当前位置共有多少条路径可达
那么dp[i][j]的路径条数怎么得到?思考后发现,dp[i][j]的条数一定是由它左边的总条数+上边的总条数,即
dp[i][j] = dp[i-1][j] + dp[i][j-1]
举个简单的例子
dp[1][1]的条数等于dp[0][1]的条数加上dp[1][0]的条数,即1+1=2
再比如
dp[2][1] = dp[1][1] + dp[2][0],而dp[1][1]=2,因此dp[2][1]总共就为三种情况
基本思路说清楚,代码就很好写了
public static int uniquePaths(int m, int n) {
// 创建一个二维数组dp,用来存储到达每个网格点的不同路径数量
int[][] dp = new int[m][n];
// 初始化第一列的值,因为在第一列的任何位置只有一条路径可以到达,即从上面一格到达
for (int i = 0; i < m; i++) {
dp[i][0] = 1;
}
// 初始化第一行的值,因为在第一行的任何位置只有一条路径可以到达,即从左边一格到达
for (int i = 0; i < n; i++) {
dp[0][i] = 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];
}
1、初始化数组 dp:dp 是一个二维数组,大小为 m x n,用于存储到达每个网格点的不同路径数量。
2、初始化第一列和第一行:因为从左上角到达第一列的任何位置和从左上角到达第一行的任何位置,只有一条路径。因此,初始化第一列和第一行的值为1。
3、填充剩余的网格点:对于其他的网格点 (i, j),路径数 dp[i][j] 等于其上方网格点 (i-1, j) 和左方网格点 (i, j-1) 的路径数之和。这是因为只能从上方或者左方到达当前格子 (i, j)。
4、返回结果:返回 dp[m-1][n-1],即右下角的格子的路径数量,这个值即为从左上角 (0, 0) 到右下角 (m-1, n-1) 的不同路径数量。
二、两数之和
题目:
给定一个整数数组 nums
和一个整数目标值 target
,请你在该数组中找出 和为目标值 target
的那 两个 整数,并返回它们的数组下标。
你可以假设每种输入只会对应一个答案。但是,数组中同一个元素在答案里不能重复出现。
思路:
这个题最简单的方法就是暴力枚举,但是时间复杂度会比较高,因此采用哈希表的方法来解题
通过元素的索引达到快速查找对应目标值的效果,从而降低时间复杂度
代码:
public int[] twoSum(int[] nums, int target) {
int[] res = new int[2]; // 创建一个长度为2的数组,用来存放结果
if (nums == null || nums.length == 0) {
return res; // 如果数组为空,直接返回空数组
}
Map<Integer, Integer> map = new HashMap<>(); // 使用HashMap来存放数组元素和它们的索引
// 遍历数组
for (int i = 0; i < nums.length; i++) {
int temp = target - nums[i]; // 计算当前元素对应的目标值,以便接下来查找对应元素
if (map.containsKey(temp)) { // 如果map中存在目标值的键
res[1] = i; // 当前元素的索引作为结果数组的第二个元素
res[0] = map.get(temp); // 获取目标值对应的索引,作为结果数组的第一个元素
break; // 找到答案后跳出循环
}
map.put(nums[i], i); // 将当前元素及其索引放入map中
}
return res; // 返回结果数组
}
具体解释为:
1、初始化结果数组 res:创建一个长度为2的整数数组 res,用于存放找到的两个索引。
2、空数组检查:如果输入数组 nums 为 null 或者长度为0,直接返回空数组 res。
3、使用HashMap存放元素和索引:创建一个 HashMap 对象 map,用来存放数组元素及其对应的索引。
4、遍历数组:使用 for 循环遍历数组 nums。
5、计算目标值:对于当前元素 nums[i],计算 temp = target - nums[i],即需要找到的另一个数。
6、检查目标值是否在HashMap中:如果 map 中存在键 temp,说明之前已经存入过与当前元素 nums[i] 相加等于 target 的元素。此时,找到了符合条件的两个索引。
7、更新结果数组:将当前元素的索引 i 存入 res[1],将 temp 对应的索引存入 res[0]。
8、将当前元素及其索引存入HashMap:如果没有找到匹配的元素,将当前元素 nums[i] 及其索引 i 存入 map 中,以便后续查找匹配项。
9、返回结果:在找到答案后,直接返回结果数组 res。
顺带解释一下map.containskey方法
在Java中,map.containsKey()
是用于检查 Map
中是否包含指定键的方法。它接受一个参数,即要检查的键,如果该键存在于 Map
中,则返回 true
;否则返回 false
。
例如:
import java.util.HashMap;
import java.util.Map;
public class Main {
public static void main(String[] args) {
Map<String, Integer> map = new HashMap<>();
// 添加一些条目到map中
map.put("apple", 10);
map.put("banana", 5);
map.put("cherry", 3);
// 检查map中是否包含特定键
String key = "banana";
if (map.containsKey(key)) {
System.out.println("Map contains key '" + key + "'");
} else {
System.out.println("Map does not contain key '" + key + "'");
}
key = "orange";
if (map.containsKey(key)) {
System.out.println("Map contains key '" + key + "'");
} else {
System.out.println("Map does not contain key '" + key + "'");
}
}
}
今天的学习就到这里了