第二十四天
1725 可以形成最大正方形的矩形数目
给你一个数组 rectangles
,其中 rectangles[i] = [li, wi]
表示第i
个矩形的长度为li
、宽度为 wi
。
如果存在 k
同时满足 k <= li
和 k <= wi
,就可以将第i
个矩形切成边长为k
的正方形。例如,矩形 [4,6]
可以切成边长最大为 4
的正方形。
设 maxLen
为可以从矩形数组 rectangles
切分得到的 最大正方形 的边长。
请你统计有多少个矩形能够切出边长为 maxLen
的正方形,并返回矩形 数目 。
方法
使用一个变量maxValue
记录最大值,maxCount
记录数量,遍历整个数组即可。
class Solution {
public int countGoodRectangles(int[][] rectangles) {
int maxCount = 0;
int maxValue = Integer.MIN_VALUE;
for (int i = 0; i < rectangles.length; ++i){
int cmpValue = Math.min(rectangles[i][0], rectangles[i][1]);
if (cmpValue == maxValue) maxCount++;
else if (cmpValue > maxValue){
maxCount = 1;
maxValue = cmpValue;
}
}
return maxCount;
}
}
47 全排列 Ⅱ
给定一个可包含重复数字的序列 nums
,按任意顺序 返回所有不重复的全排列。
方法
由于不能存在重复的元素,使用一个哈希集合来维护序列的唯一性。
class Solution {
public static List<Integer> aArray;
public static List<List<Integer>> res;
public static boolean[] isUsed;
public static HashSet<ArrayList<Integer>> set;
public List<List<Integer>> permuteUnique(int[] nums) {
isUsed = new boolean[nums.length];
set = new HashSet<>();
res = new ArrayList<>();
aArray = new ArrayList<>();
permute(nums, 0);
return res;
}
public static void permute(int[] nums, int depth){
if (depth == nums.length){
if (!set.contains(aArray)){
set.add(new ArrayList<>(aArray));
res.add(new ArrayList<>(aArray));
}
return;
}
for (int i = 0; i < nums.length; ++i){
if (!isUsed[i]){
isUsed[i] = true;
aArray.add(nums[i]);
permute(nums, depth + 1);
isUsed[i] = false;
aArray.remove(aArray.size() - 1);
}
}
}
}
39 组合总和
给你一个 无重复元素 的整数数组 candidates
和一个目标整数 target
,找出 candidates
中可以使数字和为目标数 target
的 所有 不同组合 ,并以列表形式返回。你可以按 任意顺序 返回这些组合。
candidates
中的 同一个 数字可以 无限制重复被选取 。如果至少一个数字的被选数量不同,则两种组合是不同的。
对于给定的输入,保证和为 target
的不同组合数少于 150
个。
方法
由于同一个数字可以不限制数量选取,对原有的组合算法稍作修改,当选取第i
个位置上的数字时,可以判断一下当前的总和是否没有超过目标值,如果没有超过,在当前的递归层再继续递归。
class Solution {
public static List<List<Integer>> res;
public static ArrayList<Integer> aArray;
public List<List<Integer>> combinationSum(int[] candidates, int target) {
aArray = new ArrayList<>();
res = new ArrayList<>();
backTrace(candidates, target, 0);
return res;
}
public static void backTrace(int[] nums,int target, int depth){
if (target == 0){
res.add(new ArrayList<>(aArray));
return;
}
if (depth == nums.length) return;
if (target - nums[depth] >= 0){ //如果满足条件 继续在当前层递归
aArray.add(nums[depth]);
backTrace(nums, target - nums[depth], depth);
aArray.remove(aArray.size() - 1);//少选一个
}
backTrace(nums, target, depth + 1);//选下一个
}
}
40 组合总和Ⅱ
给定一个候选人编号的集合 candidates
和一个目标数 target
,找出candidates
中所有可以使数字和为 target
的组合。
candidates
中的每个数字在每个组合中只能使用 一次 。
**注意:**解集不能包含重复的组合。
方法
由于题目要求不能存在重复的集合,因此可以先将所有数字进行排序,这样就可以让重复的元素都放在相邻的位置上。对于重复的序列[a1,a2,a3]
,如果需要保证所选出来的子集没有重复,那么我们应当在不选元素a
时,所有的元素a
都不应该选择。为此,在组合算法的原有基础之上,加上一个参数choose
,表示是否选择了上一个值。当我们遇到连续的相同值时,可以通过判断choose
值来确定连续的相同值是否应该被选择。
class Solution {
public static List<List<Integer>> res;
public static ArrayList<Integer> aArray;
public List<List<Integer>> combinationSum2(int[] candidates, int target) {
aArray = new ArrayList<>();
res = new ArrayList<>();
Arrays.sort(candidates);
backTrace(true, candidates, target, 0);
return res;
}
public static void backTrace(boolean choose, int[] nums,int target, int depth){
System.out.println(aArray);
if (target == 0) {
res.add(new ArrayList<>(aArray));
return;
}
if (target < 0 || depth == nums.length) return;
if (depth - 1 >= 0 && !choose && nums[depth - 1] == nums[depth]) {
backTrace(false, nums, target, depth + 1);
return;
}//相邻的相同的值 如果上一个值没有被选 则当前值也不应该选 直接进入下一层递归层 然后返回即可
aArray.add(nums[depth]);
backTrace(true, nums, target - nums[depth], depth + 1);//选当前值 choose为true
aArray.remove(aArray.size() - 1);
backTrace(false, nums, target, depth + 1);//不选当前值 choose为false
}
}