优化内存占用的算法需求:寻找单个可行解而非全部解
public class Test { public static void main(String[] args) { final int num = 4; final int finalCount = 8; int[][] idArr = new int[num][]; int[][] typeArr = new int[num][]; int[][] countArr = new int[num][]; idArr = new int[][]{ {1001, 2001, 3001, 4001}, {5001, 6001, 7001}, {2002, 3002, 5002, 8001}, {9001} }; typeArr = new int[][]{ {1, 2, 3, 4}, {5, 6, 7}, {2, 3, 5, 8}, {9} }; countArr = new int[][]{ {3}, {1, 2}, {2}, {1} }; } }
需求说明
从idArr中选取x个元素,需满足以下约束:
- 总量要求:
x = sum(countArr[i][0]) ≤ finalCount(0 ≤ i < countArr.length) - 分组选取规则:每个
idArr[i]中选取的元素数量y需满足y ≥ countArr[i][0]- 若
countArr[i][1]存在,则y ≤ countArr[i][1]
- 类型唯一性:选中元素对应的
type(关联typeArr)必须互不重复
当前采用回溯法枚举全部解后选取单个可行解,但内存占用过高,寻求仅生成单个可行解的优化算法方案。
优化算法方案:贪心优先+局部调整
核心思路
不枚举所有可能解,而是逐步构造单个可行解:先满足每个分组的最低选取要求,再处理类型冲突,最后根据剩余配额补充元素,全程仅维护当前构造的解状态,不存储其他候选。
具体步骤
初始化基础选取
- 遍历每个分组
i,先选取countArr[i][0]个元素,优先选择该分组中类型未被其他组基础选取占用的元素; - 若该分组的基础数量内存在类型冲突,先标记冲突类型,留待后续调整。
- 遍历每个分组
解决基础选取的类型冲突
- 遍历所有冲突类型,找到所有包含该类型的分组,尝试将其中一个分组的冲突元素替换为同组内未被选中、且类型未被占用的元素;
- 若某分组无法替换(同组剩余元素类型均已被占用),则调整其他冲突分组的元素,直到所有类型唯一。
利用剩余配额补充元素(可选)
- 计算剩余可选数量:
remaining = finalCount - sum(countArr[i][0]) - 按分组的上限(
countArr[i][1],无上限则取组内剩余元素数),依次从各分组中选取未被选中、类型未被占用的元素,直到用完剩余配额或无符合条件的元素。
- 计算剩余可选数量:
代码实现要点
- 用
HashSet<Integer>记录已占用的类型; - 用
List<List<Integer>>记录每个分组已选中的id; - 步骤1:遍历分组时,优先挑选无冲突类型的元素,若选不够最低数量则先选冲突元素并记录冲突;
- 步骤2:针对冲突类型,逐个尝试替换冲突分组内的元素,确保替换后类型唯一;
- 步骤3:补充元素时,按分组遍历,在不超过上限的前提下添加符合类型要求的元素。
优势
- 全程仅维护一个解的状态,内存占用极低;
- 避免回溯法的全量枚举,时间复杂度大幅降低;
- 若存在可行解,该方法能快速构造出一个,无需遍历所有可能性。
内容的提问来源于stack exchange,提问作者Criwran
相关产品推荐
相关产品推荐

