7月6日的五题

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: 中等

给定两个字符串 text1text2,返回这两个字符串的最长公共子序列的长度。

一个字符串的 _子序列 _是指这样一个新的字符串:它是由原字符串在不改变字符的相对顺序的情况下删除某些字符(也可以不删除任何字符)后组成的新字符串。
例如,“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: 困难

给你两个单词 word1word2,请你计算出将 word1 转换成 word2 所使用的最少操作数 。

你可以对一个单词进行如下三种操作:

  1. 插入一个字符
  2. 删除一个字符
  3. 替换一个字符

示例 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;
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值