挑战程序设计竞赛---部分和

探讨如何从整数序列中找出特定和k的子集。提供了两种方法:通过生成所有可能的子集来检查是否存在和为k的子集;使用回溯搜索递归地寻找解决方案。

题目:给定整数序列a1,a2,....,an,判断是否可以从中选出若干数,使它们的和恰好为k。

1≤n≤20

-10^8≤ai≤10^8

-10^8≤k≤10^8

样例:

输入

n = 4

a = {1,2,4,7}

k =13

输出:

Yes(13 = 2 + 4 + 7)

方法一:利用求子集方式判断那个子集中累加等于k

import java.util.*;

// 1:无需package
// 2: 类名必须Main, 不可修改

public class Main {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        SolutionTest solution = new SolutionTest();
        solution.subset(new int[]{1,2,4,7},13);

    }
}
class SolutionTest {
    public void subset(int[] arr,int k){
        int n = arr.length;
        int l = pow(2,n)-1;
        for(int i = l;i>0;i--){
            int num = 0;
            List<Integer> list = new ArrayList<>();
            for(int j = n-1;j>=0;j--){
                if(((i>>j)&1) == 1){
                    num+=arr[j];
                    list.add(arr[j]);
                }
            }
            if(num == k){
                StringBuffer sb = new StringBuffer();
                sb.append("Yes (").append(k).append(" = ");
                for(int item : list){
                    sb.append(item).append(" + ");
                }
                System.out.println(sb.substring(0,sb.length()-3)+")");
                break;
            }
        }
    }
    public int pow(int a,int n){
        if(n == 0)return 1;
        if(n == 1)return a;
        int res = a;
        int count = 1;
        while(count*2<=n){
            count*=2;
            res*=res;
        }
        return res*pow(a,n-count);
    }
}

方法二:回溯搜索

 

import java.util.*;

// 1:无需package
// 2: 类名必须Main, 不可修改

public class Main {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        SolutionTest solution = new SolutionTest();
        List<Integer> list = new ArrayList<>();
        solution.dfs(13,new int[]{1,2,4,7},13,0,list);
    }
}
class SolutionTest {
    public void dfs(int kk,int[] arr,int k,int index,List<Integer>list){
        if(k == 0){
            StringBuffer sb = new StringBuffer();
            sb.append("Yes (").append(kk).append(" = ");
            for(int item : list){
                sb.append(item).append(" + ");
            }
            System.out.println(sb.substring(0,sb.length()-3)+")");
            return;
        }
        if(k<0 || index>=arr.length){
            return;
        }
        dfs(kk,arr,k,index+1,list);
        list.add(arr[index]);
        int d = list.size()-1;
        dfs(kk,arr,k-arr[index],index+1,list);
        list.remove(d);
    }
}

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值