【LeetCode-面试经典150题-day19】

目录

39.组合总和

22.括号生成

79.单词搜索


39.组合总和

题意:

给你一个 无重复元素 的整数数组 candidates 和一个目标整数 target ,找出 candidates 中可以使数字和为目标数 target 的 所有不同组合 ,并以列表形式返回。你可以按 任意顺序 返回这些组合。

candidates 中的 同一个 数字可以 无限制重复被选取 。如果至少一个数字的被选数量不同,则两种组合是不同的。

对于给定的输入,保证和为 target 的不同组合数少于 150 个。
【输入样例】candidates = [2,3,6,7], target = 7

【输出样例】[[2,2,3],[7]]
解题思路:

1、先对数组进行排序,排序之后可以更好的比较

2、定义二维数组res存储最终的结果

3、定义函数进行递归调用,函数接收的参数有(res数组,当前路径数组path,candidates,target,当前path的和sum,以及从第index个索引开始找)

  1. 递归终止条件:当sum == target,找到一组结果,添加到res中并return结束当前的调用;

  2. 否则,继续遍历,如果sum+当前值candidates[index]以及大于taget,则终止遍历,因为刚刚排序了,后面的值越来越大;如果不大于,则把condidates[index]添加到path中,继续向下遍历

  3. 回溯操作,遍历完要移除路径path的最后一个元素,以便继续寻找可能的组合。

java 复制代码
class Solution {
    public List<List<Integer>> combinationSum(int[] candidates, int target) {
        List<List<Integer>> res = new ArrayList<>();
        Arrays.sort(candidates);
        //从第0个元素开始找,当前路径和为0
        searchPath(res,new ArrayList<>(),candidates,target,0,0);
        return res;
    }

    public void searchPath(List<List<Integer>> res, List<Integer> path,int[] candidates, int target,int sum, int index){
        //逮到了
        if(sum == target){
            res.add(new ArrayList<>(path));
            return;
        }
        for(int i=index;i<candidates.length;++i){
            if(sum + candidates[i] > target) break;//是直接跳出循环噢
            path.add(candidates[i]);
            searchPath(res,path,candidates,target,sum+candidates[i],i);//sum要加上,可以重复选,所以还是i
            path.remove(path.size()-1);//回溯回溯
        }
    }
}

时间: 击败了79.91%

内存: 击败了60.05%

22.括号生成

题意:

数字 n 代表生成括号的对数,请你设计一个函数,用于能够生成所有可能的并且 有效的括号组合。
【输入样例】n=3

【输出样例】["((()))","(()())","(())()","()(())","()()()"]
解题思路:

1、有效的括号要求是左括号的总数要小于等于右括号,才能够正确匹配。

2.、初始时,左括号的数量和右括号的数量都为n

3、当剩余的左括号数=右括号数时,下一位只能添加左括号,不然无法匹配

4、当剩余的左括号数<右括号数并且左括号数>0时,下一位可以添加左括号也可以添加右括号

5、递归结束的条件时剩余的左括号数=右括号数=0,没找到一组可能的序列,要进行回溯,删掉当前寻找序列的最后一位。ps:括号数量要记得加回去

java 复制代码
class Solution {
    public List<String> generateParenthesis(int n) {
        List<String> res = new ArrayList<>();
        if(n < 0){
            return res;
        }
        search(res,new StringBuffer(),n,n);
        return res;
    }

    public void search( List<String> res, StringBuffer str, int left, int right){
        if(left == 0 && right == 0){
            res.add(str.toString());
            return;
        }
        if(left == right){
            search(res,str.append("("),--left,right);
            //回溯,括号数量加回去
            str.deleteCharAt(str.length()-1);
            ++left;
        }else if(left < right){
            if(left > 0){
                search(res,str.append("("),--left,right);
                str.deleteCharAt(str.length()-1);
                ++left;
            }
            search(res,str.append(")"),left,--right);
            str.deleteCharAt(str.length()-1);   
            ++right;
            
        }
    }
}

时间: 击败了72.95%

内存: 击败了75.13%

79.单词搜索

题意:

给定一个 m x n 二维字符网格 board 和一个字符串单词 word 。如果 word 存在于网格中,返回 true ;否则,返回 false

单词必须按照字母顺序,通过相邻的单元格内的字母构成,其中"相邻"单元格是那些水平相邻或垂直相邻的单元格。同一个单元格内的字母不允许被重复使用。
【输入样例】board = [["A","B","C","E"],["S","F","C","S"],["A","D","E","E"]], word = "ABCCED"

【输出样例】true
解题思路:

1、由于同一个单元格内的字母不允许重复使用,定义二维boolean数据存储哪一个坐标元素已经使用

2、先遍历整个二维数组,寻找可能的开始元素board[i][j]

3、找到第一个单元格后,要上下左右寻找符合单词的第二个字母的单元格,没找到返回false,找到继续找第三、第四,同理,没找到要返回false,返回后,返回上一个符合要求的单元格(回溯),看其余三个方向是否有满足条件的

4、递归的终止条件是访问的单元格=单词字符串的长度(true),或者上文说的上下左右都不符合下一位(false)

本题解法参考:leetcode回溯算法经典例题------单词搜索

java 复制代码
class Solution {
    public boolean exist(char[][] board, String word) {
        int m = board.length;
        int n = board[0].length;
        boolean[][] use = new boolean[m][n];
        for (int i = 0; i < m; i++) {
            for (int j = 0; j < n; j++) {
                if (board[i][j] == word.charAt(0)){
                    use[i][j] = true;
                    if (search(use,i, j, 1, word, board))
                        return true;
                    else use[i][j] = false;
                }
            }
        }
        return false;
    }
 
    public boolean search(boolean[][] use, int m, int n, int i, String word, char[][] board) {
        if (i == word.length()) return true;
        else {
            if (m > 0 && board[m - 1][n] == word.charAt(i)&& !use[m - 1][n] ) {
                use[m - 1][n] = true;
                if (search(use, m - 1, n, i + 1, word, board))
                    return true;
                else use[m - 1][n] = false;
            }
            if (m < board.length - 1&& board[m + 1][n] == word.charAt(i) && !use[m + 1][n] ) {
                use[m + 1][n] = true;
                if (search(use, m +1, n, i + 1, word, board))
                    return true;
                else use[m + 1][n] = false;
            }
            if (n < board[0].length - 1 && board[m][n+1] == word.charAt(i) && !use[m][n+1] ) {
                use[m][n+1] = true;
                if (search(use, m, n+1, i + 1, word, board))
                    return true;
                else use[m][n+1] = false;
            }
            if (n > 0 && board[m][n-1] == word.charAt(i) && !use[m][n-1] ) {
                use[m][n-1] = true;
                if (search(use, m, n-1, i + 1, word, board))
                    return true;
                else use[m][n-1] = false;
            }
            return false;
        }
    }
}

时间: 击败了95.20%

内存: 击败了96.67%

相关推荐
passer__jw7671 小时前
【LeetCode】【算法】3. 无重复字符的最长子串
算法·leetcode
passer__jw7671 小时前
【LeetCode】【算法】21. 合并两个有序链表
算法·leetcode·链表
sweetheart7-71 小时前
LeetCode22. 括号生成(2024冬季每日一题 2)
算法·深度优先·力扣·dfs·左右括号匹配
SRY122404192 小时前
javaSE面试题
java·开发语言·面试
__AtYou__3 小时前
Golang | Leetcode Golang题解之第557题反转字符串中的单词III
leetcode·golang·题解
2401_858286113 小时前
L7.【LeetCode笔记】相交链表
笔记·leetcode·链表
景鹤4 小时前
【算法】递归+回溯+剪枝:78.子集
算法·机器学习·剪枝
_OLi_4 小时前
力扣 LeetCode 704. 二分查找(Day1:数组)
算法·leetcode·职场和发展
丶Darling.4 小时前
Day40 | 动态规划 :完全背包应用 组合总和IV(类比爬楼梯)
c++·算法·动态规划·记忆化搜索·回溯
风影小子5 小时前
IO作业5
算法