给定一个整数数组 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 不对应任何字母。
示例 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);
}
}