LeetCode子集问题:位运算两种写法为何一个触发内存超限?
子集问题位运算代码内存超限原因分析
我尝试用位运算解决Subsets问题,最初写的代码运行时触发Memory Limit Exceeded错误:
class Solution { public List<List<Integer>> subsets(int[] nums) { int num=(int)Math.pow(2,nums.length); List<List<Integer>> ans = new ArrayList<>(); for(int i=0;i<num;i++) { List<Integer> ls = new ArrayList<>(); int addNum=nums.length-1; while(i>0) { if((i&1)!=0) { ls.add(nums[addNum]); } addNum--; i=i>>1; } ans.add(ls); } return ans; } }
后来看到另一位用户的代码,逻辑类似但用了辅助函数,能正常通过测试:
class Solution { public List<List<Integer>> subsets(int[] nums) { List<List<Integer>> ans=new ArrayList<>(); int num = (int)Math.pow(2,nums.length); for(int i=0;i<num;i++) { List<Integer> ls = helper(i,nums); ans.add(ls); } return ans; } public List<Integer> helper(int i, int[] nums) { List<Integer> ls = new ArrayList<>(); int j=0; while(i>0) { int rem=i&1; if(rem==1) { ls.add(nums[j]); } j++; i=i>>1; } return ls; } }
想请教为什么第一段代码会内存超限?
核心原因:循环变量被意外修改导致无限循环
第一段代码的致命问题是在for循环内部直接修改了循环控制变量i:
- 在
while(i>0)循环中,执行i=i>>1会直接改变for循环的控制变量值。 - 举个典型场景:当
i=1时,进入while循环后i会被右移为0,while循环结束。此时for循环的i++会把i变回1,导致for循环永远卡在i=1的状态,无法递增到num。 - 无限循环会持续创建新的
ArrayList并添加到结果集合中,最终耗尽内存,触发Memory Limit Exceeded错误。
而第二段代码通过辅助函数规避了这个问题:
- 辅助函数的参数
i是原循环变量的副本,在helper方法中修改的是这个副本的值,完全不会影响外部for循环的控制变量。 - for循环能正常从0遍历到
num-1,内存使用始终保持在合理范围。
内容的提问来源于stack exchange,提问作者RAKSHA PADIYAR
相关产品推荐
相关产品推荐

