求正数数组的最小不可组成和

给定一个全是正数的数组arr,定义一下arr的最小不可组成和的概念: 1,arr的所有非空子集中,把每个子集内的所有元素加起来会出现很多的值,其中最小的记为min,最大的记为max; 2,在区间[min,max]上,如果有一些正数不可以被arr某一个子集相加得到,那么这些正数中最小的那个,就是arr的最小不可组成和; 3,在区间[min,max]上,如果所有的数都可以被arr的某一个子集相加得到,那么max+1是arr的最小不可组成和; 举例: arr = {3,2,5} arr的min为2,max为10,在区间[2,10]上,4是不能被任何一个子集相加得到的值中最小的,所以4是arr的最小不可组成和; arr = {3,2,4} arr的min为2,max为9,在区间[2,9]上,8是不能被任何一个子集相加得到的值中最小的,所以8是arr的最小不可组成和; arr = {3,1,2} arr的min为1,max为6,在区间[2,6]上,任何数都可以被某一个子集相加得到,所以7是arr的最小不可组成和; 请写函数返回arr的最小不可组成和。

public class Solution {

    /**
     * 正数数组中的最小不可组成和 输入:正数数组arr 返回:正数数组中的最小不可组成和
     */
    public static int getFirstUnFormedNum(int[] arr) {
        int max = arr[0];

        for (int i = 1; i < arr.length; i++) {
            max += arr[i];
        }
        for (int i = 0; i < arr.length; i++) {
            for (int j = 0; j + 1 < arr.length - i; j++) {
                if (arr[j] > arr[j + 1]) {
                    int temp = arr[j];
                    arr[j] = arr[j + 1];
                    arr[j + 1] = temp;
                }
            }
        }
        int min = arr[0];
        int m[][] = new int[arr.length + 1][max + 1];

        for (int j = min; j < max + 1; j++){
            for (int i = 1; i < arr.length + 1; i++) {
                if (arr[i-1] <= j) {
                    m[i][j] = Math.max(m[i - 1][j - arr[i-1]] + arr[i-1], m[i - 1][j]);
                } else {
                    m[i][j] = m[i - 1][j];
                }
            }
            if(m[arr.length][j]!=j){
                return j;
            }
        }
        return max+1;

    }

    public static void main(String[] args) {
        int[] arr = { 2, 3, 5 };
        System.out.println(Solution.getFirstUnFormedNum(arr));;
    }

}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Prim 算法是一种用于解加权无向图的最小生成树的算法,可以处理边权为正数的情况。但是,当边权为负数时,我们需要对 Prim 算法进行一些修改。下面介绍一种可以处理边权为正负数的 Prim 算法。 假设无向图 G 有 n 个结点和 m 条边,边权可以为正数或负数。Prim 算法的主要思想是从图中任选一个结点作为起始结点,然后将其它结点逐个加入到生成树中,直到所有结点都被加入到生成树中为止。在加入结点的过程中,每次选择一条从生成树中的结点到其它结点的最小边,将其它结点加入到生成树中,并更新其它结点到生成树中的距离。 下面给出 Prim 算法处理边权为正负数的具体实现步骤: 1. 选择一个任意结点作为起始结点,将其加入到生成树中。 2. 对于生成树中的每个结点,找到与其相连的边中权值最小的那条边所连接的结点,将其加入到生成树中,同时记录该边的权值。 3. 重复步骤 2 直到所有结点都被加入到生成树中为止。 需要注意的是,由于边权存在负数,我们不能像普通的 Prim 算法一样使用堆来维护当前结点到生成树的最小距离。为了解决这个问题,我们需要使用优先队列(Priority Queue)来维护当前结点到生成树的最小距离,并且需要使用一个布尔数组来记录每个结点是否已经被加入到生成树中。 具体实现时,我们可以定义一个结构体 Edge 来存储图中的边,包括边的起点、终点和权值。然后使用一个二维数组来存储图中每个结点到其它结点的边的权值,如果两个结点之间没有边,则将其权值设为一个较大的数。最后使用一个数组 dist 来记录每个结点到生成树的最小距离,初始值为边权数组的第一个元素。 下面给出一个 C++ 代码实现示例:
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值