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

目录

17.电话号码的字母组合

 77.组合

46.全排列 

52.N皇后Ⅱ 


17.电话号码的字母组合

题意:

给定一个仅包含数字 2-9 的字符串,返回所有它能表示的字母组合。答案可以按 任意顺序 返回。

给出数字到字母的映射如下(与电话按键相同)。注意 1 不对应任何字母。

【输入样例】digits="23"

【输出样例】["ad","ae","af","bd","be","bf","cd","ce","cf"]

class Solution {
    public List<String> letterCombinations(String digits) {
        List<String> ans = new ArrayList<String>();
        if(digits.length() == 0){
            return ans;
        }
        Map<Character,String> phoneMap = new HashMap<Character,String>(){
    
    {
            put('2',"abc");
            put('3',"def");
            put('4',"ghi");
            put('5',"jkl");
            put('6',"mno");
            put('7',"pqrs");
            put('8',"tuv");
            put('9',"wxyz");
        }};

        findString(ans,phoneMap,digits,0,new StringBuffer());
        return ans;
    }

    public void findString(List<String> ans, Map<Character,String> phoneMap,
    String digits,int index,StringBuffer curAns){
        if(index == digits.length()){
            //证明全部遍历完比
            ans.add(curAns.toString());
            //把找到的答案转成String类型存到列表中
        }else{
            char digit = digits.charAt(index);//取出字符,到map中获取对应的值
            String letters = phoneMap.get(digit);
            for(int i=0;i<letters.length();++i){
                curAns.append(letters.charAt(i));
                //递归调用,主要是用于找到下一位可能的字符
                findString(ans,phoneMap,digits,index+1,curAns);
                //递归回来进行回溯,把当前的字符删掉,寻找更多可能
                curAns.deleteCharAt(index);
            }
        }
    }
}

时间: 击败了46.35%

内存: 击败了26.39%

 77.组合

题意:

给定两个整数 n 和 k,返回范围 [1, n] 中所有可能的 k 个数的组合。

你可以按 任何顺序 返回答案。

【输入样例】n=4,k=2

【输出样例】

[
  [2,4],
  [3,4],
  [2,3],
  [1,2],
  [1,3],
  [1,4],
]
class Solution {

    List<List<Integer>> ans = new ArrayList<List<Integer>>();
    
    public List<List<Integer>> combine(int n, int k) {
        findAns(1,n,k,new ArrayList<>());//从1开始找
        return ans;

    }
    public void findAns(int index,int n,int k,List<Integer> list){

        if(k == 0){
            //找到正确的答案,添加
            ans.add(new ArrayList<>(list));
            return;
        }
        for(int i=index;i<=n-k+1;++i){
            list.add(i);
            findAns(i+1,n,k-1,list);
            list.remove(list.size()-1);
        }
    }
}

时间: 击败了56.50%

内存: 击败了5.94%

46.全排列 

题意:

给定一个不含重复数字的数组 nums ,返回其 所有可能的全排列 。你可以 按任意顺序 返回答案。

【输入样例】nums=[1,2,3]

【输出样例】[[1,2,3],[1,3,2],[2,1,3],[2,3,1],[3,1,2],[3,2,1]]

解题思路:递归回溯+哈希表

1. 构建一个哈希map,用来存放当前那一些数字可以用,那一些数字不可以用;

2. 递归函数的作用是找到第index位上可以是那个数字,数字是位于数字中,所以对数组进行枚举来获得第i位的值,之后用哈希map判断此位数字是否已经被用过。被用过继续找,没被用过则添加到list中,并修改标志位,继续寻找第index+1位;

3.回溯的时候除了要移开最后一位数字,还需要重新修改标志位。

class Solution {
    List<List<Integer>> ans = new ArrayList<List<Integer>>();
    
    public List<List<Integer>> permute(int[] nums) {
        //构造map,初始化所有数字现在都可以用
        int len = nums.length;
        Map<Integer,Boolean> useMap= new HashMap<Integer,Boolean>();
        for(int i=0;i<len;++i){
            useMap.put(nums[i],true);
        }
        searchOrder(1,nums,len,useMap,new ArrayList<>());//从第一位开始找
        return ans;
    }

    public void searchOrder(int index,int[] nums,int len,Map<Integer,Boolean> useMap,List<Integer> list){
        if(index == len+1){
            //找到正确的答案,添加
            ans.add(new ArrayList<>(list));
            return;
        }
        for(int i=0; i < len;++i){
            //从第一位到最后一位,可以选择那一些
            int num = nums[i];
            if(useMap.get(num) == true){
                list.add(num);
                //修改标志位
                useMap.put(num,false);
                searchOrder(index+1,nums,len,useMap,list);
                list.remove(list.size()-1);
                useMap.put(num,true);
            }
        }
    }
}

时间: 击败了78.23%

内存: 击败了48.52% 

52.N皇后Ⅱ 

题意:

n 皇后问题 研究的是如何将 n 个皇后放置在 n × n 的棋盘上,并且使皇后彼此之间不能相互攻击。

给你一个整数 n ,返回 n 皇后问题 不同的解决方案的数量。

【输入样例】n=4

【输出样例】2

解题思路:递归回溯+布尔数组

为什么是!row[i] && !dia[index-i+n] && !assDia[index+i]?

row[i]:好理解,同一列已经有值

but,dia和assDia中的取值为什么是这样书写的呢?

class Solution {
    int ans = 0;
    
    public int totalNQueens(int n) {
        //n皇后问题
        //任意两个皇后不能在同一横轴,纵轴,对角线上
        //三个数组,表示当前纵轴,正对角线,副对角线上是否有值,默认false
        boolean[] row = new boolean[n+1];
        boolean[] dia = new boolean[2*n+1];
        boolean[] assDia = new boolean[2*n+1];
        search(1,n,row,dia,assDia);//从第一行开始判断
        
        return ans;
    }

    private void search(int index,int n, boolean[] row, boolean[] dia, boolean[] assDia){
        if(index == n+1){
            ++ans;
            return;
        }
        //index表示当前查找第几行,所以遍历遍历列就可以了
        for(int i=1;i<=n;i++){
            if(!row[i] && !dia[index-i+n] && !assDia[index+i]){
                row[i] = dia[index-i+n] = assDia[index+i] = true;//已经有值
                search(index+1,n,row,dia,assDia);
                //回溯
                row[i] = dia[index-i+n] = assDia[index+i] = false;
                
            }
        }
    }
}

时间: 击败了100.00%

内存: 击败了74.08% 

猜你喜欢

转载自blog.csdn.net/qq_37998848/article/details/132582902