LeeCode 39 组合总和(天坑啊java的值传递,头都被打懵了)

本文深入解析LeetCode第39题“组合总和”的解决方案,探讨了如何寻找所有可能的数字组合使它们的和等于给定的目标数。文章详细解释了递归算法的实现细节,并分享了在Java中因值传递导致的问题及解决方法。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

给定一个无重复元素的数组 candidates 和一个目标数 target ,找出 candidates 中所有可以使数字和为 target 的组合。

candidates 中的数字可以无限制重复被选取。

说明:

  • 所有数字(包括 target)都是正整数。
  • 解集不能包含重复的组合。 

示例 1:

输入: candidates = [2,3,6,7], target = 7,
所求解集为:
[
  [7],
  [2,2,3]
]

示例 2:

输入: candidates = [2,3,5], target = 8,
所求解集为:
[
  [2,2,2,2],
  [2,3,3],
  [3,5]
]

啊,此题真是,一言难尽啊,先上报错代码(因为一直找不到错误,还以为逻辑错了,就把C/C++的正确代码重写了一遍,没想到还是一直报错,最后灵机一动,想到值传递这件事,才AC代码):

package LeetCode;
import java.util.*;

public class Lee_39_SumOfZuHe {
	public static void main(String[] args){
		int[] candidates = new int[]{2,3,6,7};
		int target = 7;
		new Lee_39_SumOfZuHe().combinationSum(candidates,target);
	}
    public List<List<Integer>> combinationSum(int[] candidates, int target) {
    	List<List<Integer>> list = new ArrayList<List<Integer>>();
   	
     	List<Integer> mylist = new ArrayList<Integer>();;
    	Arrays.sort(candidates);
    	//System.out.println(Arrays.toString(candidates));
    	ReccombinationSum(candidates,target,0,mylist,list);
    	//System.out.print(list);
    	return list;
    }
    public void ReccombinationSum(int[] Newcandidates,int sum,int start,List<Integer> mylist,List<List<Integer>> list){
        if(sum<0)
    		return;
        else if(sum==0){
    		list.add(mylist);
    		return;
    	}
    	else{
    		for(int i=start;i<Newcandidates.length;i++){
    			int current = Newcandidates[i];
    			mylist.add((Integer)current);
    			ReccombinationSum(Newcandidates,sum-current,i,mylist,list);	//主要是此行代码
    			mylist.remove((Integer)current);
    		}
    	}
    }
}

结果跑出了空结果:

加了一行检测代码,发现能跑出正确结果,说明只是list没能真正添加元素:

那么问题出在哪呢?难受啊兄die~~~

后面理解了值传递,改了代码:

    			ReccombinationSum(Newcandidates,sum-current,i,mylist,list);		
    			ReccombinationSum(Newcandidates,sum-current,i,new ArrayList<Integer>(mylist),list);		

可以看见,主要是在递归过程中重新创建了对象,其实理解了java的值传递模式就能理解了,当mylist作为形参进行传递时,传递的是mylist的地址值,当然可以通过对mylist的地址值对对象进行操作,然而如果不重新new一个mylist出来,在进行list.add(mylist)的时候,只会把这一个对象进行add,然而再往后递归的时候,由于mylist是一个对象,mylist先add后remove自然会将mylist清空,而list真正add的其实是mylist的地址,add了两次其实是add了mylist这一个对象两次,然后mylist又被清空,所以结果只能是[ [ ] , [ ] ],更改代码后,结果AC~~~

话说回来,博主之前也做过类似的递归题,不过由于用的不是list这样通过地址值传递的递归,而是利用String 进行递归,没出现问题,现在想来,String作为不可变量,每次更改时其实都是重新申请了String对象,暗合值传递理念,只能说博主还是太年轻啊~~引以为鉴!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值