70. 爬楼梯
1143. 最长公共子序列
72. 编辑距离
73. 矩阵置零
剑指 Offer 40. 最小的k个数
--------------------------------------------------------------------------
70. 爬楼梯
Difficulty: 简单
假设你正在爬楼梯。需要 n 阶你才能到达楼顶。
每次你可以爬 1 或 2 个台阶。你有多少种不同的方法可以爬到楼顶呢?
**注意:**给定 n 是一个正整数。
示例 1:
输入: 2
输出: 2
解释: 有两种方法可以爬到楼顶。
1\. 1 阶 + 1 阶
2\. 2 阶
示例 2:
输入: 3
输出: 3
解释: 有三种方法可以爬到楼顶。
1\. 1 阶 + 1 阶 + 1 阶
2\. 1 阶 + 2 阶
3\. 2 阶 + 1 阶
Solution:斐波拉切数列的变形
class Solution {
public int climbStairs(int n) {
if(n == 1) return 1;
if(n == 2) return 2;
int x1 = 1, x2 = 2, res = 0;
for(int i=3; i<=n; i++){
res = x1 + x2;
x1 = x2;
x2 = res;
}
return res;
}
}
1143. 最长公共子序列
Difficulty: 中等
给定两个字符串 text1
和 text2
,返回这两个字符串的最长公共子序列的长度。
一个字符串的 _子序列 _是指这样一个新的字符串:它是由原字符串在不改变字符的相对顺序的情况下删除某些字符(也可以不删除任何字符)后组成的新字符串。
例如,“ace” 是 “abcde” 的子序列,但 “aec” 不是 “abcde” 的子序列。两个字符串的「公共子序列」是这两个字符串所共同拥有的子序列。
若这两个字符串没有公共子序列,则返回 0。
示例 1:
输入:text1 = "abcde", text2 = "ace"
输出:3
解释:最长公共子序列是 "ace",它的长度为 3。
示例 2:
输入:text1 = "abc", text2 = "abc"
输出:3
解释:最长公共子序列是 "abc",它的长度为 3。
示例 3:
输入:text1 = "abc", text2 = "def"
输出:0
解释:两个字符串没有公共子序列,返回 0。
提示:
1 <= text1.length <= 1000
1 <= text2.length <= 1000
- 输入的字符串只含有小写英文字符。
Solution:动态规划
class Solution {
public int longestCommonSubsequence(String text1, String text2) {
if(text1.length()<=0 || text2.length()<=0) return 0;
int len1 = text1.length(), len2 = text2.length();
//dp[i][j]:text1的前i个字符串,和text2的前j个字符串最长的公共子序列
int[][] dp = new int[len1+1][len2+1];
for(int i=1; i<=len1; i++){
for(int j=1; j<=len2; j++){
if(text1.charAt(i-1) == text2.charAt(j-1)){
dp[i][j] = dp[i-1][j-1]+1;
}
else{
dp[i][j] = Math.max(dp[i][j-1], dp[i-1][j]);
}
}
}
return dp[len1][len2];
}
}
72. 编辑距离
Difficulty: 困难
给你两个单词 word1 和 word2,请你计算出将 word1 转换成 word2 所使用的最少操作数 。
你可以对一个单词进行如下三种操作:
- 插入一个字符
- 删除一个字符
- 替换一个字符
示例 1:
输入:word1 = "horse", word2 = "ros"
输出:3
解释:
horse -> rorse (将 'h' 替换为 'r')
rorse -> rose (删除 'r')
rose -> ros (删除 'e')
示例 2:
输入:word1 = "intention", word2 = "execution"
输出:5
解释:
intention -> inention (删除 't')
inention -> enention (将 'i' 替换为 'e')
enention -> exention (将 'n' 替换为 'x')
exention -> exection (将 'n' 替换为 'c')
exection -> execution (插入 'u')
Solution:动态规划,和上一题对比着看
class Solution {
public int minDistance(String word1, String word2) {
int len1 = word1.length(), len2 = word2.length();
//定义状态
//dp[i][j] 表示 word1的前i个字符和word2前j个字符,最少经过dp[i][j]步可相等
int[][] dp = new int[len1+1][len2+1];
//初始化------------------------------
//通过删除 word1中的元素
for(int i=1; i<=len1; i++){
dp[i][0] = dp[i-1][0]+1;
}
//通过添加 word1中的元素
for(int j=1; j<=len2; j++){
dp[0][j] = dp[0][j-1]+1;
}
for(int i=1; i<=len1; i++){
for(int j=1; j<=len2; j++){
if(word1.charAt(i-1) == word2.charAt(j-1)){
dp[i][j] = dp[i-1][j-1];
}
else{
//dp[i][j-1]表示添加word1[i] 或者删除word2[j]
//dp[i-1][1]表示删除word1[i] 或者添加word2[j]
//dp[i-1][j-1]表示替换word1[i] 或者替换word2[j]
dp[i][j] = Math.min(dp[i][j-1], dp[i-1][j]);
dp[i][j] = Math.min(dp[i][j], dp[i-1][j-1]);
dp[i][j]++;
}
}
}
return dp[len1][len2];
}
}
73. 矩阵置零
Difficulty: 中等
给定一个 m x n 的矩阵,如果一个元素为 0,则将其所在行和列的所有元素都设为 0。请使用算法**。**
示例 1:
输入:
[
[1,1,1],
[1,0,1],
[1,1,1]
]
输出:
[
[1,0,1],
[0,0,0],
[1,0,1]
]
示例 2:
输入:
[
[0,1,2,0],
[3,4,5,2],
[1,3,1,5]
]
输出:
[
[0,0,0,0],
[0,4,5,0],
[0,3,1,0]
]
进阶:
- 一个直接的解决方案是使用 O(m__n) 的额外空间,但这并不是一个好的解决方案。
- 一个简单的改进方案是使用 O(m + n) 的额外空间,但这仍然不是最好的解决方案。
- 你能想出一个常数空间的解决方案吗?
Solution:题目要求使用常量空间。将第0行和第0列的每个元素,作为这一行或者这一列是否出现过0的标志位,然后再单独处理第0行和第0列
class Solution {
public void setZeroes(int[][] matrix) {
int m = matrix.length;
if(m <= 0) return;
int n = matrix[0].length;
if(n <= 0) return;
boolean rowFlag = false; //记录第0行是否有0
for(int i=0; i<n; i++){
if(matrix[0][i] == 0){
rowFlag = true;
break;
}
}
boolean columnFlag = false; //记录第0列是否有0
for(int i=0; i<m; i++){
if(matrix[i][0] == 0){
columnFlag = true;
break;
}
}
//找寻哪些行和哪些列要被置为0
for(int i=1; i<m; i++){
for(int j=1; j<n; j++){
if(matrix[i][j] == 0){
matrix[i][0] = 0; //在第0列记录下来,之后这一列全部设置为0
matrix[0][j] = 0; //在第0行记录下来,之后这一行全部设置为0
}
}
}
//遍历刚刚记录在第0行的0,如果是0则整列都为0
for(int i=1; i<n; i++){
if(matrix[0][i] == 0){
for(int j=1; j<m; j++){
matrix[j][i] = 0;
}
}
}
//遍历刚刚记录在第0列的0,如果是0则整行都为0
for(int i=1; i<m; i++){
if(matrix[i][0] == 0){
for(int j=1; j<n; j++){
matrix[i][j] = 0;
}
}
}
//如果第0行一开始就有0
if(rowFlag){
for(int i=0; i<n; i++){
matrix[0][i] = 0;
}
}
//如果第0列一开始就有0
if(columnFlag){
for(int i=0; i<m; i++){
matrix[i][0] = 0;
}
}
}
}
剑指 Offer 40. 最小的k个数
Difficulty: 简单
输入整数数组 arr
,找出其中最小的 k
个数。例如,输入4、5、1、6、2、7、3、8这8个数字,则最小的4个数字是1、2、3、4。
示例 1:
输入:arr = [3,2,1], k = 2
输出:[1,2] 或者 [2,1]
示例 2:
输入:arr = [0,1,2,1], k = 1
输出:[0]
限制:
0 <= k <= arr.length <= 10000
0 <= arr[i] <= 10000
Solution:优先队列(小根堆)
class Solution {
public int[] getLeastNumbers(int[] num, int k) {
int[] res = new int[k];
//小根堆
PriorityQueue<Integer> smallHeap = new PriorityQueue<>();
for(int i=0; i<num.length; i++){
smallHeap.offer(num[i]);
}
for(int i=0; i<k; i++){
int top = smallHeap.poll();
System.out.println(top);
res[i] = top;
}
return res;
}
}