Leetcode刷题训练第五周

文章目录

Backtracking

Leetcode 401easy

  • 解题思路:
    • 此题关键点在于理解题意
      • 分钟为必须为2位数,可以包含开头为0,例如"1:2"是不合法的,应为"1:02"
      • 小时位不允许开头为0,例如"01:00"是不合法的,应为"1:00"
      • 代表分钟的一列有6个灯,分别是[1, 2, 4, 8, 16, 32], 表示0~59区间(分钟最大显示是59,到60为0)
      • 代表小时的一列有4个灯,分别是[1, 2, 4, 8],表示0~11区间(因为小时最大是11,到12即为0点)
    • 要找出指定灯数下所有可能出现的情况,可以使用回溯算法解决,比暴力解法效率要高,因为可能出现的情况较多
      • 定义一个数组,初始化将小时范围和分钟范围的值全部放入

        int[] arr = {1,2,4,8,1,2,4,8,16,32};
        
      • 在backtracking的过程中我们需要知道在某个位置,当前值是小时还是分钟,因此我们定义一个方法判断是小时还是分钟

        private boolean isHour(int pos) {
            return pos >= 0 && pos <= 3;
        }
        
      • 定义backtracking方法,使用标准backtracking模板

        /** 
        arr: 需要遍历的数组
        pos: 数组的索引
        hour: 当前小时的值
        minute: 当前分钟的值
        led: 当前led数
        ret: 当前的所有可能的时间列表
        **/
        private void backtracking(int[] arr, int pos, int hour, int minute, int led, List<String> ret) {
            // 递归终止条件: 当led为0时,将当前小时和分钟写入列表
            if (led == 0) {
                // 根据上面的说明,小时最大显示11,分钟最大显示59
                if (hour <= 11 && minute <= 59) {
                    StringBuilder sb = new StringBuilder();
                    // 分钟的处理
                    sb.append(hour).append(":").append(minute <= 9 : "0" + minute : minute);
                    ret.add(sb.toString());
                }
                return;
            }
        
            // 开始遍历
            for (int i = pos; i < arr.length; i ++) {
                // 若是小时则小时叠加当前值
                if (isHour(i)) {
                    hour += arr[i];
                } else {
                    minute += arr[i];
                }
        
                // 递归pos + 1,led则-1
                backtracking(arr, pos + 1, hour, minute, led - 1, ret);
        
                // 移除叠加
                if (isHour(i)) {
                    hour -= arr[i];
                } else {
                    minute -= arr[i];
                }
            }
        }
        
      • 在主方法中初始化调用backtracking

        // 初始化索引pos为0,小时为0,分钟为0
        backtracking(arr, 0, 0, 0, led, ret);
        
        

Leetcode 77: Combinationsmedium

  • 解题思路:
    • 根据题意获取关键信息
      • 子数组长度为k
      • 子数组中最大值不超过n
      • 无需考虑排序,找到所有可能的子集
    • 使用backtracking来穷举
      • 定义一个数组缓存所有可能的子集,这里可以在全局定义,便于回溯时更新子集元素,无需每次都创建新的子集数组
        private int[] tmp;
        
      • 定义backtracking方法,考虑所需要的参数
        • 最后的返回集合(List<List> ret)
        • 子数组长度(int k)
        • 数组最大值(int n)
        • 索引值(int index)
            private void backtracking(List<List<String>> ret, int n, int index, int k) {
                // 递归终止条件
                // 当index到k + 1位置时结束递归,开始将当前tmp数组转化为list并插入返回的集合
                if (index == k + 1) {
                    List<Integer> subList = new ArrayList<>();
                    for (int i: tmp) {
                        subList.add(i);
                    }
                    ret.add(subList);
                    return;
                }
            
                // 定义当前索引值
                int curr = (index == 1) ? 1: tmp[index - 2] + 1;
                // 开始遍历
                for (int i = curr; i <= n; i ++) {
                    tmp[index - 1] = i;
                    backtracking(ret, n, index + 1, k);
                }
            }
          
      • 最后在主方法中调用,然后返回ret集合即可
        tmp = new int[k];
        List<List<Integer>> ret = new ArrayList<>();
        backtracking(ret, n, 1, k);
        return ret;
        

Leetcode 46: Permutationsmedium

  • 解题思路
    • 全排列是比较经典的回溯算法题,穷举出集合中任意的可能排列项
      •   // 主函数中我们初始化backtracking方法中的参数
          // 选择链表结构,便于在递归过程中移除节点,更新操作
          LinkedList<Integer> tmp = new LinkedList<>();
          backtracking(nums, tmp);
        
      • 开始进行backtracking递归
        private void backtracking(int[] nums, LinkedList<Integer> tmp) {
            // 递归结束条件
            // 当tmp的大小等于nums数组长度,说明元素都已经在tmp中填充完毕,此时将tmp添加到返回列表中
            if (tmp.size == nums.length) {
                ret.add(new LinkedList(tmp));
                return;
            }
        
            for (int i = 0; i < nums.length; i ++) {
                // 若tmp中包含nums[i],则跳过往下执行
                if (tmp.contains(nums[i])) continue;
        
                // 将元素添加到tmp中
                tmp.add(nums[i]);
                backtracking(nums, tmp);
                tmp.removeLast();
                
            }
        }
        

Leetcode 51: N-Queenshard

  • TODO: explanation
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值