2044. 统计按位或能得到最大值的子集数目【中等题】【每日一题】
思路:【二进制枚举】
- 设nums长度为len,nums的子集共有2^len-1种情况,可以用一个长度为len的二进制数来枚举所有子集的状态,第i位为0表示子集不选取nums中第i个位置,为1表示子集选取nums中第i个位置。
- 那么遍历每一个二进制表示的状态,判断当前状态都有哪些位置被选中(与1按位与,结果为1说明当前位置被选中),将选中的nums[j]全部进行按位或计算,得到的答案res与max比较,比max大则将max更新为max,ans置1;与max相等则ans++,比max小则什么也不做。
- 最后返回ans即可。
代码:
class Solution {
public int countMaxOrSubsets(int[] nums) {
int max = 0,ans = 0,len = nums.length;
for (int i = 0; i < 1<<len; i++) {
int res = 0;
for (int j = 0; j < len; j++) {
if (((i>>j) & 1) == 1){//判断当前状态i的第j位是否被选中
res |= nums[j];
}
}
if (res>max){
max = res;
ans = 1;
}else if (res == max){
ans++;
}
}
return ans;
}
}
90. 子集 II【中等题】
思路:【二进制枚举】
- 依然是二进制枚举求所有子集,但这次需要对子集去重,即如果两个子集里边的所有元素都相同,那么需要去掉。
- 那如何判断两个子集是否重复呢?先对数组进行排序,如果当前元素与上一个元素相同,且上一个元素没被选择而当前元素被选择了,那么当前这个即将生成的子集必然会与上一个子集重复,此时需要跳过这个子集的生成,且不能将其添加到答案中。
- 将不会重复的子集添加到答案中并返回。
代码:
class Solution {
public List<List<Integer>> subsetsWithDup(int[] nums) {
List<List<Integer>> ans = new ArrayList<>();
List<Integer> list = new ArrayList<>();
Arrays.sort(nums);
int len = nums.length;
for (int i = 0; i < 1 << len; i++) {
list.clear();
boolean flag = false;
for (int j = 0; j < len; j++) {
if (((i >> j) & 1) == 1){
if (j > 0 && nums[j] == nums[j-1] && ((i>>(j-1)) & 1) == 0){
flag = true;
break;
}
list.add(nums[j]);
}
}
if (flag){
continue;
}
ans.add(new ArrayList<>(list));
}
return ans;
}
}
223. 矩形面积【中等题】
思路:
- 道理大家都懂,两个总面积等于两个矩形的面积-重合面积,如果不重合,就减0,即不减。
- 求两个矩形的面积直接拿捏,那么怎么判断矩形是否重合,以及如果重合,那么饿重合面积怎么算?
- 先假设存在重合,且重合部分的矩形,左下角坐标为(mx1,my1),右上角坐标为(mx2,my2),那么显然根据这个左下角坐标和右上角坐标我们就可以算出重叠矩形的长 l 和宽 w ,现在,如果假设成立,那么重叠矩形的长和宽肯定都得是正数,要不然假设就不成立,于是重叠矩形的面积就是0。
- 那么现在的首要目标就是,找出这个假设中的重合矩形的左下角坐标(mx1,my1)和右上角坐标(mx2,my2),注意了啊,现在假设这个矩形是存在的,那么你画张两个矩形交叉的图,观察一下就能得出结论:
- 左下角横坐标等于两个矩形左下角横坐标的较大值,左下角纵坐标等于两个矩形左下角纵坐标的较大值;右上角横坐标等于两个矩形右上角横坐标的较小值,右上角纵坐标等于两个矩形右上角纵坐标的较小值。
- 于是宽w=mx2-mx1,长 l = my2-my1,那么如果长款均大于0,则重合面积 s等于w * l ,否则重合面积s = 0;
- 最后返回 s1 + s2 - s。
代码:
class Solution {
public int computeArea(int ax1, int ay1, int ax2, int ay2, int bx1, int by1, int bx2, int by2) {
int s1 = (ax2-ax1)*(ay2-ay1),s2 = (bx2-bx1)*(by2-by1),s = 0;
int mx1 = Math.max(ax1,bx1),my1 = Math.max(ay1,by1);
int mx2 = Math.min(ax2,bx2),my2 = Math.min(ay2,by2);
int w = mx2-mx1,l = my2-my1;
s = Math.max(w,0)*Math.max(l,0);
return s1+s2-s;
}
}