组合相关问题

1.组合

在这里插入图片描述
组合

本题可以说是组合的经典问题了。一般该题我们使用回溯算法,结合树型结构完成

在这里插入图片描述
根据上图再结合代码

class Solution {
    LinkedList<Integer> path = new LinkedList<>();//存放组合
    List<List<Integer>> res = new ArrayList<>();//输出结果
    public List<List<Integer>> combine(int n, int k) {
        backTrack(n,k,1);
        return res;
    }

    void backTrack(int n,int k,int startIndex){
        //终止条件,即递归结束需要输出结论
        if(path.size()==k){
            res.add(new ArrayList<>(path));
            return;
        }

        //单层递归
        for(int i = startIndex;i<=n;i++){
            path.add(i);
            backTrack(n,k,i+1);//递归,进入下一层for循环,取出下一个数
            path.removeLast();//回溯
        }
    }
}

2.组合总和 III

在这里插入图片描述
组合总和 III

两题基本一致,唯一不同的是本题新增参数sum来记录值

class Solution {
	List<List<Integer>> result = new ArrayList<>();
	LinkedList<Integer> path = new LinkedList<>();

	public List<List<Integer>> combinationSum3(int k, int n) {
		backTracking(n, k, 1, 0);
		return result;
	}

	private void backTracking(int targetSum, int k, int startIndex, int sum) {
		// // 减枝
		// if (sum > targetSum) {
		// 	return;
		// }

		if (path.size() == k) {
			if (sum == targetSum) result.add(new ArrayList<>(path));
			return;
		}
		
		// 减枝 9 - (k - path.size()) + 1
		for (int i = startIndex; i <= 9; i++) {
			path.add(i);
			sum += i;
			backTracking(targetSum, k, i + 1, sum);
			//回溯
			path.removeLast();
			//回溯
			sum -= i;
		}
	}
}

3.电话号码的字母组合

在这里插入图片描述
电话号码的字母组合

创建一个字符串,放入数组中。根据给的的 digits 的数字取出,映射到字符串中。然后就和上两题相似。

class Solution {
    List<String> list = new ArrayList<>();
    public List<String> letterCombinations(String digits) {
        if(digits==null||digits.length()==0) return list;
        String[] resources = {"","","abc","def","ghi","jkl","mno","pqrs","tuv","wxyz"};

        breakTrack(digits,resources,0);
        return list;
    }

    StringBuilder sb = new StringBuilder();
    //index表示不是字母的第几个位置,而是digits的第几位(0,1,2....)
    void breakTrack(String digits,String[] resources,int index){
        
        //终止条件
        if(index==digits.length()){
            list.add(sb.toString());
            return;
        }
        //将数字转换为对应的字母
        String str = resources[digits.charAt(index)-'0'];//类型转换
        for(int i=0;i<str.length();i++){
            sb.append(str.charAt(i));
            //递归
            breakTrack(digits,resources,index+1);
            //回溯
            sb.deleteCharAt(sb.length()-1);
        }
    }
}

4. 组合总和

在这里插入图片描述
组合总和

class Solution {
   
    public List<List<Integer>> combinationSum(int[] candidates, int target) {
         List<Integer> path = new ArrayList<>();
        List<List<Integer>> ans = new ArrayList<>();
        backTrack(candidates,target,path,ans,0,0);
        return ans;
    }

    void backTrack(int[] candidates, int target,List<Integer> path,List<List<Integer>> ans,int sum,int index){
        //终止条件
        if(sum>target){
            return;
        }
        if(sum==target){
            ans.add(new ArrayList<>(path));
            return;
        }

        for(int i =index;i<candidates.length;i++){
            sum+=candidates[i];
            path.add(candidates[i]);
            candidates(candidates,target,path,ans,sum,i);
            path.remove(path.size()-1);
        }
    }
}

5. 组合总和 II

在这里插入图片描述
组合总和 II

由于不能出现重复的集合,所以本题的关键就是去重。创建一个boolean数组。同层无需去重,同树枝需要去重。

class Solution {
    List<List<Integer>> lists = new ArrayList<>();
    Deque<Integer> deque = new LinkedList<>();
    int sum=0;
    /**
        去重的思路是去重同一树枝的,不去同一层的
        建立一个boolea数组,若该值和前一个值不相等,说明是同一层,要去重
     */
    public List<List<Integer>> combinationSum2(int[] candidates, int target) {
        //为了将重复的数字放在一起,要先排序
        Arrays.sort(candidates);
        boolean[] flag = new boolean[candidates.length];
        backTrack(candidates,target,flag,0);
        return lists;
    }

    public void backTrack(int[] candidates, int target,boolean[] flag,int index){
        //终止条件
        if(sum==target){
            lists.add(new ArrayList<>(deque));
            return;
        }

        for(int i=index;i<candidates.length&&sum+candidates[i]<=target;i++){
            //去重,判断是同层值等还是同枝值等
            if(i>0&&candidates[i]==candidates[i-1]&&!flag[i-1]){
                continue;
            }
            //同层
            deque.push(candidates[i]);
            sum+=candidates[i];
            flag[i]=true;
            //同枝
            backTrack(candidates,target,flag,i+1);
            int temp = deque.pop();
            flag[i]=false;
            sum-=temp;
        }
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
投资组合问题是金融领域中的一个经典问题。其目标是在给定的一组资产和相关的风险-收益数据的情况下,找到一个最优的投资组合,以最大化投资回报并最小化风险。 Gurobi是一个用于数学优化的软件包,可以用来解决投资组合问题。以下是一个简单的投资组合问题的Gurobi实现: 假设我们有4个资产,每个资产的收益率和方差如下: | 资产 | 收益率 | 方差 | |:---:|:-----:|:----:| | A | 0.10 | 0.005 | | B | 0.15 | 0.010 | | C | 0.12 | 0.008 | | D | 0.08 | 0.003 | 我们的目标是找到一个最优的投资组合,使得总收益率最大,同时总方差不超过0.01。假设我们有100万资金可以投资,并且每个资产可以购买的数量是连续的。 我们可以使用Gurobi建立一个模型来解决这个问题: ```python import gurobipy as gp # 创建模型 model = gp.Model() # 创建决策变量 x = model.addVars(4, lb=0, ub=1000000) # 添加目标函数 model.setObjective(gp.quicksum(x[i] * ret[i] for i in range(4)), sense=gp.GRB.MAXIMIZE) # 添加约束条件 model.addConstr(gp.quicksum(x[i] * var[i] for i in range(4)) <= 0.01) model.addConstr(gp.quicksum(x[i] for i in range(4)) == 1000000) # 求解模型 model.optimize() # 输出结果 for i in range(4): print("Asset {}: {}".format(i+1, x[i].x)) ``` 在这个例子中,我们首先创建了模型对象,然后创建了4个决策变量x1、x2、x3和x4,表示我们要购买每个资产的数量。然后,我们添加了目标函数,最大化总收益率,以及两个约束条件:总方差不超过0.01,投资总额为100万。 最后,我们调用模型的optimize()方法,求解模型,并输出结果。在这个例子中,最优解是: ``` Asset 1: 374999.9999999999 Asset 2: 625000.0000000001 Asset 3: 0.0 Asset 4: 0.0 ``` 这意味着我们应该投资37.5万资金购买资产A,62.5万资金购买资产B,不投资C和D。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值