leetcode-zgd-day52-300.最长递增子序列/674.最长连续递增序列/718.最长重复子数组/剑指offer 12.矩阵中的路径

103 阅读1分钟

300.最长递增子序列

题目链接:300. 最长递增子序列 - 力扣(Leetcode)

解题思路:

这几个题都类似,最关键的地方在于确定dp数组的含义,不要盲目的认为题目的问题就是dp数组的定义。有的时候需要转换思维。

 class Solution {
     public int lengthOfLIS(int[] nums) {
         /**
          * 1.dp[i] 以下标i为序列结尾的最长严格递增子序列的长度
          * 2.if(nums[i] > nums[j]) dp[i] = Math.max(dp[i], dp[j] + 1);
          * 3.dp[0] = 0;
          */
         int[] dp = new int[nums.length];
         Arrays.fill(dp, 1);
         int result = 1;
         for (int i = 1; i < dp.length; i++) {
             for(int j = 0; j < i; j++){
                 if(nums[i] > nums[j]){
                     dp[i] = Math.max(dp[i], dp[j] + 1);
                 }
             }
             result = Math.max(result, dp[i]);
         }
         return result;
     }
 }

674.最长连续递增序列

题目链接:674. 最长连续递增序列 - 力扣(Leetcode)

解题思路:

 class Solution {
     public int findLengthOfLCIS(int[] nums) {
         /**
          * 动态规划
          * 1.dp[i] 以nums[i]为结尾的连续递增子序列的最大长度
          * 2.if(nums[i - 1] < nums[i]) dp[i] = dp[i - 1] + 1;
          *   else dp[i] = 0;
          * 3.dp[i] = 1;
          * 4.正向循环
          */
         int[] dp = new int[nums.length];
         Arrays.fill(dp, 1);
         int ans = 1;
         for (int i = 1; i < dp.length; i++) {
             if(nums[i - 1] < nums[i]) dp[i] = dp[i - 1] + 1;
             else dp[i] = 1;
             ans = Math.max(ans, dp[i]);
         }
         return ans;
     }
 }

718.最长重复子数组

题目链接:718. 最长重复子数组 - 力扣(Leetcode)

解题思路:

这个题需要注意的就是dp数组的初始化问题。不可以仅仅初始化(0,0)。

 class Solution {
     public int findLength(int[] nums1, int[] nums2) {
         /**
          * 1.dp[i][j] 以nums1[i]结尾以及nums2[j]结尾的子数组的最长公共长度
          * 2.if(nums1[i] == nums2[j]) dp[i][j] = dp[i - 1][j - 1] + 1;
          *   else dp[i][j] = 0;
          */
         int ans = 0;
         int[][] dp = new int[nums1.length + 1][nums2.length + 1];
         for(int i = 0; i < nums1.length; i++){
             if(nums1[i] == nums2[0]) dp[i][0] = 1;
             ans = Math.max(ans, dp[i][0]);
         }
         for(int i = 1; i < nums2.length; i++){
             if(nums1[0] == nums2[i]) dp[0][i] = 1;
             ans = Math.max(ans, dp[0][i]);
         }
         for (int i = 1; i < nums1.length; i++) {
             for (int j = 1; j < nums2.length; j++) {
                 if(nums1[i] == nums2[j]) dp[i][j] = dp[i - 1][j - 1] + 1;
                 ans = Math.max(ans, dp[i][j]);
             }
         }
         return ans;
     }
 }

剑指offer 12.矩阵中的路径

题目链接:剑指 Offer 12. 矩阵中的路径 - 力扣(Leetcode)

解题思路:

 class Solution {
     public boolean exist(char[][] board, String word) {
         /**
         首先找到起始首字母,然后进行递归判断
         */
         char sw = word.charAt(0);
         int m = board.length;
         int n = board[0].length;
         boolean[][] used = new boolean[m][n];
         for(int i = 0; i < m; i++){
             for(int j = 0; j < n; j++){
                 if(board[i][j] == sw){             
                     if(hasWord(board, used, word, i, j, 0) == true) return true;
                 }
             }
         }
         return false;
     }
     public boolean hasWord(char[][] board, boolean[][] used, String word, int x, int y, int index){
         // 判断是否不需要该字符。长度已经够了
         if(index == word.length()) return true;
         // 判断横纵坐标是否符合要求,没有越界
         if(x < 0 || x >= board.length) return false;
         if(y < 0 || y >= board[0].length) return false;
         // 判断元素是否已经被使用
         if(used[x][y] == true) return false;
         // 判断元素是否匹配
         if(board[x][y] != word.charAt(index)) return false;
         used[x][y] = true;
         // 继续判断下一个元素
         boolean left = hasWord(board, used, word, x - 1, y, index + 1);
         boolean right = hasWord(board, used, word, x + 1, y, index + 1);
         boolean up = hasWord(board, used, word, x, y + 1, index + 1);
         boolean down = hasWord(board, used, word, x, y - 1, index + 1);
         used[x][y] = false;
         return left || right || up || down;
     }
 }