【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个索引开始找)

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

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

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

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:括号数量要记得加回去

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回溯算法经典例题——单词搜索

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%

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值