回溯算法编程题集合(leetcode)

简介: 回溯算法编程题集合(leetcode)

给定一个整数数组  nums 和一个正整数 k,找出是否有可能把这个数组分成 k 个非空子集,其总和都相等。


示例 1:


输入: nums = [4, 3, 2, 3, 5, 2, 1], k = 4

输出: True

说明: 有可能将其分成 4 个子集(5),(1,4),(2,3),(2,3)等于总和。

示例 2:


输入: nums = [1,2,3,4], k = 3

输出: false


来源:力扣(LeetCode)

链接:https://leetcode.cn/problems/partition-to-k-equal-sum-subsets


本题一开始本人打算使用动态规划,一开始的思路是求得nums数组的和然后除以k赋值为target,然后利用动态规划01背包求nums数组中可以组成target的方案数,但是运用此题理解有偏差,因为是划分子集所以有些数组元素不能重复使用。


选用leetcode精选题解


力扣

 public boolean canPartitionKSubsets(int[] nums, int k) {
        int sum = 0;
        for (int i = 0; i < nums.length; i++) sum += nums[i];
        if (sum % k != 0) return false;
        int target = sum / k;
        // 排序优化
        Arrays.sort(nums);
        int l = 0, r = nums.length - 1;
        while (l <= r) {
            int temp = nums[l];
            nums[l] = nums[r];
            nums[r] = temp;
            l++;
            r--;
        }
        return backtrack(nums, 0, new int[k], k, target);
    }
    private boolean backtrack(int[] nums, int index, int[] bucket, int k, int target) {
        // 结束条件优化
        if (index == nums.length) return true;
        for (int i = 0; i < k; i++) {
            // 优化点二
            if (i > 0 && bucket[i] == bucket[i - 1]) continue;
            // 剪枝
            if (bucket[i] + nums[index] > target) continue;
            bucket[i] += nums[index];
            if (backtrack(nums, index + 1, bucket, k, target)) return true;
            bucket[i] -= nums[index];
        }
        return false;
    }

491. 递增子序列


难度中等639收藏分享切换为英文接收动态反馈


给你一个整数数组 nums ,找出并返回所有该数组中不同的递增子序列,递增子序列中 至少有两个元素 。你可以按 任意顺序 返回答案。


数组中可能含有重复元素,如出现两个整数相等,也可以视作递增序列的一种特殊情况。


示例 1:

输入:nums = [4,6,7,7]

输出:[[4,6],[4,6,7],[4,6,7,7],[4,7],[4,7,7],[6,7],[6,7,7],[7,7]]


示例 2:

输入:nums = [4,4,3,2,1]

输出:[[4,4]]

 public static List<List<Integer>> findSubsequences(int[] nums) {
        List<List<Integer>> lists=new ArrayList<>();
        if(nums.length<2)
            return lists;
        List<Integer> list=new ArrayList<>();
        backtreeing(lists,list,0,nums);
        return lists;
    }
    public static void backtreeing(List<List<Integer>> lists,List<Integer> list,int start,int nums[]){
         if(list.size()>=2){
             lists.add(new ArrayList<>(list));
         }
         //set做树层剪枝,同一层已经使用过的元素再此使用就跳出
        HashSet<Integer> set=new HashSet<>();
        for(int i=start;i<nums.length;i++){
            if(i>start&&set.contains(nums[i]))
                continue;
            if(list.size()==0||nums[i]>=list.get(list.size()-1)){
                list.add(nums[i]);
                set.add(nums[i]);
                backtreeing(lists,list,i+1,nums);
                list.remove(list.size()-1);
            }
        }
    }

17. 电话号码的字母组合

难度中等2418收藏分享切换为英文接收动态反馈

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

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

711e62888bbd0451bcb45ff69411bc74.png

示例 1:

输入:digits = "23"

输出:["ad","ae","af","bd","be","bf","cd","ce","cf"]


示例 2:

输入:digits = ""

输出:[]

示例 3:

输入:digits = "2"

输出:["a","b","c"]

 public List<String> letterCombinations(String digits) {
        List<String> list=new ArrayList<>();
        if(digits==null||digits.length()==0)
            return list;
        char[] chars = digits.toCharArray();
        StringBuilder stringBuilder=new StringBuilder();
        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");
        }};
        backtreeing(chars,list,phoneMap,stringBuilder,0);
        return list;
    }
    public void backtreeing(char[] chars,List<String> list,Map<Character,String> map,   StringBuilder stringBuilder,int start){
       if(start==chars.length){
           list.add(stringBuilder.toString());
           return;
       }
        String s1 = map.get(chars[start]);
        for(int i=0;i<s1.length();i++){
           stringBuilder.append(s1.charAt(i));
           backtreeing(chars,list,map,stringBuilder,start+1);
           stringBuilder.deleteCharAt(stringBuilder.length()-1);
       }
    }

93. 复原 IP 地址


难度中等1203收藏分享切换为英文接收动态反馈


有效 IP 地址 正好由四个整数(每个整数位于 0 到 255 之间组成,且不能含有前导 0),整数之间用 '.' 分隔。


例如:"0.1.2.201" 和 "192.168.1.1" 是 有效 IP 地址,但是 "0.011.255.245"、"192.168.1.312" 和 "192.168@1.1" 是 无效 IP 地址。

给定一个只包含数字的字符串 s ,用以表示一个 IP 地址,返回所有可能的有效 IP 地址,这些地址可以通过在 s 中插入 '.' 来形成。你 不能 重新排序或删除 s 中的任何数字。你可以按 任何 顺序返回答案。


示例 1:

输入:s = "25525511135"

输出:["255.255.11.135","255.255.111.35"]


示例 2:

输入:s = "0000"

输出:["0.0.0.0"]


示例 3:

输入:s = "101023"

输出:["1.0.10.23","1.0.102.3","10.1.0.23","10.10.2.3","101.0.2.3"]

 public static List<String> restoreIpAddresses(String s) {
        List<String> list=new ArrayList<>();
        if(s.length()<4)
            return list;
        String[] num=new String[4];
        backtreeing(s,list,0,0,num);
        return list;
    }
    public static void backtreeing(String s,List<String> list,int start,int count,String[] num){
        if(count==4){
            if(start==s.length()){
                StringBuilder stringBuilder=new StringBuilder();
                for(int i=0;i<num.length;i++){
                   stringBuilder.append(num[i]);
                   if(i!=3)
                       stringBuilder.append(".");
                }
                list.add(stringBuilder.toString());
            }
            return;
        }
        //if 语句不能放在外面因为在执行过程中start会超出字符串长度,导致异常,比如10.10.23 count=3,start=6的时候就会错误
//        if(s.charAt(start)=='0'){
//            num[count] = "0";
//            backtreeing(s, list, start + 1, count + 1, num);
//            return;
//        }
        StringBuilder stringBuilder=new StringBuilder();
        for(int i=start;i<s.length();i++){
            if(s.charAt(start)=='0'){
                num[count] = "0";
                backtreeing(s, list, start + 1, count + 1, num);
                return;
            }
            if(i>start+2)
                break;
            String substring = s.substring(start, i + 1);
            if(Integer.parseInt(substring)>255)
                continue;
            stringBuilder.append(substring);
            num[count]=stringBuilder.toString();
            backtreeing(s,list,i+1,count+1,num);
             stringBuilder.delete(0,stringBuilder.length()+1);
        }
    }

相关文章
|
8天前
|
机器学习/深度学习 人工智能 算法
回溯算法是怎样的
回溯算法,择优搜索:树的深搜+剪枝
|
14天前
|
算法 Java
[Java·算法·简单] LeetCode 283. 移动零
[Java·算法·简单] LeetCode 283. 移动零
17 2
|
14天前
|
算法 Java
[Java·算法·中等] LeetCode21. 合并两个有序链表
[Java·算法·中等] LeetCode21. 合并两个有序链表
15 2
|
17天前
|
存储 算法 调度
力扣中级算法(Python)
力扣中级算法(Python)
|
17天前
|
算法 C++
【数据结构与算法】:关于时间复杂度与空间复杂度的计算(C/C++篇)——含Leetcode刷题-2
【数据结构与算法】:关于时间复杂度与空间复杂度的计算(C/C++篇)——含Leetcode刷题
|
17天前
|
算法 C++
【数据结构与算法】:关于时间复杂度与空间复杂度的计算(C/C++篇)——含Leetcode刷题-1
【数据结构与算法】:关于时间复杂度与空间复杂度的计算(C/C++篇)——含Leetcode刷题
|
5天前
|
算法 Java
Java数据结构与算法:用于处理不相交集合的合并和查找问题
Java数据结构与算法:用于处理不相交集合的合并和查找问题
|
6天前
|
算法 搜索推荐 C++
C++之STL常用算法(遍历、查找、排序、拷贝、替换、算数生成、集合)
C++之STL常用算法(遍历、查找、排序、拷贝、替换、算数生成、集合)
14 0
|
7天前
|
人工智能 算法 搜索推荐
Java算法编程详解和程序实例
Java算法编程详解和程序实例
14 0
|
18天前
|
算法
【经典LeetCode算法题目专栏分类】【第11期】递归问题:字母大小写全排列、括号生成
【经典LeetCode算法题目专栏分类】【第11期】递归问题:字母大小写全排列、括号生成