> 文档中心 > day15-算法每日4题

day15-算法每日4题


64. 最小路径和

class Solution {   /     * 给定一个包含非负整数的 mxn网格grid ,请找出一条从左上角到右下角的路径,使得路径上的数字总和为最小。     * 说明:每次只能向下或者向右移动一步。     * 动态规划     * 从左上角(0,0)->(i,j)的最小路径和     * dp(grid,i,j) = Math.min( dp(grid,i - 1 ,j) , dp(grip,i,j-1 ) ) + grid[i][j];     */    // 备忘录    int[][] memo;    public int minPathSum(int[][] grid) { if (grid == null || grid.length == 0) return 0; /// 列长 int m = grid.length; // 行长 int n = grid[0].length; // 记录到每一个坐标时的路径和 memo = new int[m][n]; // 先给出默认值 for (int[] row : memo) {     Arrays.fill(row, 0); } return dp(grid, m - 1, n - 1);    }    private int dp(int[][] grid, int i, int j) { // 如果只有一个元素 if (i == 0 && j == 0) return grid[0][0]; if (i < 0 || j < 0) return Integer.MAX_VALUE; // 避免重复计算 if (memo[i][j] != 0) {     return memo[i][j]; } // 将计算记过记录备忘录 memo[i][j] = Math.min(dp(grid, i - 1, j), dp(grid, i, j - 1)) + grid[i][j]; return memo[i][j];    }}

658. 找到 K 个最接近的元素

class Solution {    /     * 给定一个 排序好 的数组arr ,两个整数 k 和 x ,从数组中找到最靠近 x(两数之差最小)的 k 个数。返回的结果必须要是按升序排好的。     * 

* 整数 a 比整数 b 更接近 x 需要满足: *

* |a - x| < |b - x| 或者 * |a - x| == |b - x| 且 a < b * 我们可以将数组中的元素按照与目标 x 的差的绝对值排序,排好序后前 k 个元素就是我们需要的答案。 */ public List<Integer> findClosestElements(int[] arr, int k, int x) { if (arr == null || arr.length == 0) return null; // 自动装箱进行初始化 List<Integer> res = Arrays.stream(arr).boxed() .sorted((a, b) -> Objects.equals(a, b) ? 0 : Math.abs(a - x) - Math.abs(b - x)) .collect(Collectors.toList()); // |a - x| - |b - x | 升序 // 截取k个 res = res.subList(0, k); Collections.sort(res); return res; }}

3. 无重复字符的最长子串

class Solution {  /     * 给定一个字符串 s ,请你找出其中不含有重复字符的 最长子串 的长度。     * 滑动窗口     */    public int lengthOfLongestSubstring(String s) { if (s == null || s.length() == 0) return 0; // 用来存储每个字母出现的次数 // 每次循环窗口里面的内容有没有重复来进行左边界和右边界来移动 Set<Character> set = new HashSet<>(); // 窗口的左边界和右边界 int l = 0, r = 0; int maxWin = 0; // 左右两边不能超过字符串的长度 while (l < s.length() && r < s.length()) {     // 判断当前扩张边界的字符是否已经在set中存在了     if (set.contains(s.charAt(r))) {  // 将set中左边界元素移除,并且左边界往前移动  set.remove(s.charAt(l));  l++;     } else {  // 将右边界的元素添加到set中,并且右边界往前移动  set.add(s.charAt(r));  r++;  // 计算最大窗口,右边界 - 左边界  maxWin = Math.max(maxWin, r - l);     } } return maxWin;    }}

824. 山羊拉丁文

class Solution {  /     * 给你一个由若干单词组成的句子sentence ,单词间由空格分隔。每个单词仅由大写和小写英文字母组成。     * 请你将句子转换为 “山羊拉丁文(Goat Latin)”(一种类似于 猪拉丁文- Pig Latin 的虚构语言)。山羊拉丁文的规则如下:     * 如果单词以元音开头('a', 'e', 'i', 'o', 'u'),在单词后添加"ma"。     * 例如,单词 "apple" 变为 "applema" 。     * 如果单词以辅音字母开头(即,非元音字母),移除第一个字符并将它放到末尾,之后再添加"ma"。     * 例如,单词 "goat" 变为 "oatgma" 。     * 根据单词在句子中的索引,在单词最后添加与索引相同数量的字母'a',索引从 1 开始。     * 例如,在第一个单词后添加 "a" ,在第二个单词后添加 "aa" ,以此类推。     * 返回将 sentence 转换为山羊拉丁文后的句子。     */      Set<Character> vowels = new HashSet<Character>() { {     add('a');     add('e');     add('i');     add('o');     add('u');     add('A');     add('E');     add('I');     add('O');     add('U'); }    };    String suffix = "ma";    public String toGoatLatin(String sentence) { if (sentence == null || sentence.length() == 0) return ""; StringBuilder res = new StringBuilder(); String[] words = sentence.split(" "); for (int i = 0; i < words.length; i++) {     // 处理单个单词     StringBuilder generatedWord = generateSingle(words[i]).append("a".repeat(Math.max(0, i + 1))).append(" ");     res.append(generatedWord); } return res.toString().trim();    }    private StringBuilder generateSingle(String word) { StringBuilder res = new StringBuilder(); // 判断第一个字母是不是元音字母 if (vowels.contains(word.charAt(0))) res = new StringBuilder(word + suffix); else res.append(word.substring(1)).append(word.charAt(0)).append(suffix); return res;    }}