java数据结构与算法之求所有子数组问题
Posted wen-pan
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了java数据结构与算法之求所有子数组问题相关的知识,希望对你有一定的参考价值。
- 求数组子数组的题目是很多类似题目的基础,所以一定要明白如何求一个数组的【所有子数组】
- 注意:这里讨论的是求数组的【所有子数组】和下面的求数组的【所有连续子数组】问题区分开
①、题目描述
- 给你一个整数数组nums,求该数组的所有子数组
- 比如:nums = [1,2,3]
- 返回,[ [1,2,3], [1,2], [1,3], [1], [2], [3], [2,3], [] ]
②、类似题目
③、代码
- 核心就是使用递归去做决策,对于数组中的每个位置都可以选择【要或者不要】
- 如果要当前位置的数,那么继续递归决策他的下一个位置
- 如果不要当前位置的数,那么继续递归决策他的下一个位置
- 当决策完数组中最后一个位置时,开始收集前面做好的决策结果(每次收集便得到一个子数组)
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-xPtpLf06-1647590976752)(picture/子数组问题.png)]
/**
* 给你一个数组nums,求该数组的子数组集合
*
* @param nums 数组
* @return List 子数组集合
*/
public static List<List<Integer>> subArrayList(int[] nums)
List<List<Integer>> list = new ArrayList<>();
if (nums == null || nums.length < 1)
return list;
// 递归决策
process(nums, 0, new ArrayList<>(), list);
return list;
/**
* 求这种问题,对于每个位置都有两种选择,要或者不要
*
* @param nums 数组
* @param index 当前来到的位置
* @param decisionResult 每一个位置的决策结果存放集合
* @param resultList 最终结果集
*/
public static void process(int[] nums, int index, List<Integer> decisionResult, List<List<Integer>> resultList)
// 决策完数组最后一个位置后,将结果记录到resultList
if (nums.length == index)
// 注意:Java中list是引用类型,所以这里需要将决策完的结果【拷贝一份】然后放入结果集
List<Integer> copy = new ArrayList<>(decisionResult);
resultList.add(copy);
return;
// 对于每个位置都有两种选择,要或者不要,定了index位置后,然后去决策index + 1 位置
// 1、要当前位置的数
decisionResult.add(nums[index]);
process(nums, index + 1, decisionResult, resultList);
// 2、不要当前位置的数(这里注意要把上面add的数remove掉,注意这里是按照数组下标remove的)
// 注意这里始终是remove的最后一个元素
decisionResult.remove(decisionResult.size() - 1);
process(nums, index + 1, decisionResult, resultList);
④、题目进阶
统计按位或能得到最大值的子集数目
- 给你一个整数数组 nums ,请你找出 nums 子集 按位或 可能得到的 最大值 ,并返回按位或能得到最大值的 不同非空子集的数目
- 如果数组 a 可以由数组 b 删除一些元素(或不删除)得到,则认为数组 a 是数组 b 的一个 子集 。如果选中的元素下标位置不一样,则认为两个子集 不同 。
- 对数组 a 执行 按位或 ,结果等于 a[0] OR a[1] OR … OR a[a.length - 1](下标从 0 开始)。
class Solution
// 最大值
int max = -1;
// 出现次数
int count = 0;
// 暴力递归解法(也就是求所有子集,对于每个位置都可以选择要或者不要)
public int countMaxOrSubsets(int[] nums)
process(nums,0,0);
return count;
/*
* 递归求得每一个子集,对于每一个位置都可以选择要或者不要
*
* @param nums 数组
* @param index 当前来到的位置
* @param orRes 异或的结果
*/
public void process(int[] nums,int index, int orRes)
if(index >= nums.length)
// 结算,只记录最大值以及他的次数
if(orRes > max)
// orRes大于当前的max,那么说明新发现了比之前的max还要大的数,就将count重置为1
max = orRes;
count = 1;
else if(orRes == max)
// orRes等于当前的max,那么就把count++
count++;
// orRes小于当前的max,那么就什么也不做
return;
// 要当前位置
process(nums,index + 1,orRes | nums[index]);
// 不要当前位置
process(nums,index + 1,orRes);
以上是关于java数据结构与算法之求所有子数组问题的主要内容,如果未能解决你的问题,请参考以下文章