Java List与地址相关的一点坑

Java 踩坑系列 (一)List

踩坑过程

今天刷回溯法 leetcode-77-组合 的时候。因为返回值是 List<List>,所以可以使用一个 List 的对象来进行回溯。于是我想当然的写出了以下代码:

List<List<Integer>> ans = new ArrayList<List<Integer>>();

    private void backTracking(int start, int n, int k, List<Integer> temp) {
        if (temp.size() == k) { //当temp的size已经是k时,加入到ans中,退出
            ans.add(temp);
            return;
        }
        for (int i = start; i <= n; i++) { //因为不考虑重复的{「1,2」和「2,1」算重复,这里还没有剪枝
            temp.add(i);
            backTracking(i + 1, n, k, temp); //回溯
            temp.remove(temp.size() - 1); //回溯完,往上
        }
    }

    public List<List<Integer>> combine(int n, int k) {
        List<Integer> temp = new ArrayList<>(); //
        backTracking(1, n, k, temp);
        return ans;
    }

	 	public static void main(String[] args) {
        Solution solution = new Solution();
        List<List<Integer>> combine = solution.combine(4, 2);
        System.out.println(combine);
    }

结果运行的时候,出来的结果是这样的

[[], [], [], [], [], []]

原因

分析结果:返回值是规模是正确的,但是里面的值全都神秘消失了。

我调试了一遍程序,发现每一轮 temp 都被顺利加入到了 ans 中。但是当我对 temp 进行回溯时,会移除前一步中加入的元素,此时 ans 里加入的 temp 也发生了变化。`实际上,在这段代码里ans中的每个子元素都指向 temp。因此当 temp 变化时,ans 里的每个元素也发生了变化。最后的回溯将 temp 清空了,所以也就出现了上面的情况。于是对代码稍做修改,答案就正确了:

List<List<Integer>> ans = new ArrayList<List<Integer>>();
private void backTracking(int start, int n, int k, List<Integer> temp) {
    if (temp.size() == k) { //当temp的size已经是k时,加入到ans中,退出
        List<Integer> cur = new ArrayList<>(temp);
        ans.add(cur);
        return;
    }
    for (int i = start; i <= n; i++) { //因为不考虑重复的{「1,2」和「2,1」算重复,这里还没有剪枝
        temp.add(i);
        backTracking(i + 1, n, k, temp); //回溯
        temp.remove(temp.size() - 1); //回溯完,往上
    }
}

public List<List<Integer>> combine(int n, int k) {
    List<Integer> temp = new ArrayList<>(); 
    backTracking(1, n, k, temp);
    return ans;
}

[[1, 2], [1, 3], [1, 4], [2, 3], [2, 4], [3, 4]]

最后对第 8 行稍做修改,实现剪枝操作,就能较快的 AC 了

 for (int i = start; i <= n - (k - temp.size()) + 1; i++) { //因为不考虑重复的{「1,2」和「2,1」算重复
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值