区间内选择整数求和

116 阅读3分钟

问题描述

小S拥有三个正整数:LR 和 S。他想知道能否从 L 到 R(包含 L 和 R)之间选择一些整数,使它们的总和正好等于 S

请注意,从 L 到 R 的每个整数最多只能选择一次。如果可以找到满足条件的整数集合,请返回 1,否则返回 0

例如:当 L = 5R = 8S = 12 时,可以选择整数 5 和 7,因为它们的和是 12,所以答案为 1


测试样例

样例1:

输入:L = 5,R = 8,S = 12
输出:1

样例2:

输入:L = 3,R = 10,S = 17
输出:1

思路: 首先我们注意到[L,R]是一个连续的区间,我们要在里面选出几个不重复的数而且这些数加起来刚好等于S。我们不知道需要几个数的和,并且这几个数是怎么分布的。比如1、2、3、4、5、6、7、8、9、10需要找到和是15的数,可以是2个数的和(5、10)、(7、8)、(6、9)也可以是5个数(1、2、3、4、5)。就上面1到10的例子,我们可以知道n个数最小值是前面n个数的和,最大值是后面n个的和,然后因为L到R是连续的,所以得到的n个数的最小值到最大值也是连续的,我们可以在这些数里面随便找n个数结果肯定落在这个区间里面。

所以可以创建两个数组来分别记录这些数的和,small[i],记录了L从L开始连续i+1个数的和,big[i]记录了L+i到R这些数的和。


public class 区间内选择整数求和 {

    public static int solution(int L, int R, int S) {
       int max=(L+R)*(R-L+1)/2;
       //如果全部加起来还没他大,那么就必定不会超过他
        if(max<S){
            return 0;
        }
        int length=R-L+1;
        int[] small=new int[length];
        int[] big=new int[length];
        int i;
        small[0]=L;
        big[length-1]=R;
        for(i=1;i<length;i++){
            small[i]+=small[i-1]+L+i;
        }

        for(i=length-2;i>=0;i--){
            //注意i是递减的,他和R的规律
            big[i]=big[i+1]+L+i;
        }
        //得到的是n。。。3、2、1个数相加的和,需要反转
        i=0;
        int j=length-1,tmp;
        while(i<j){
            tmp=big[i];
            big[i]=big[j];
            big[j]=tmp;
            i++;
            j--;
        }
        //System.out.println(Arrays.toString(small));
        //System.out.println(Arrays.toString(big));
        //看看数落在哪几个数的和的区间,最后一个一开始判断了,所以这里不用判断
        for(i=0;i<length-1;i++){
            if(S>=small[i]&&S<=big[i]){
                return 1;
            }
        }

        return 0;


    }

    public static void main(String[] args) {
        //System.out.println(solution(5, 8, 12));
        System.out.println(solution(5, 8, 12) == 1);
        System.out.println(solution(3, 10, 17) == 1);
        System.out.println(solution(1, 5, 20) == 0);
    }
}

代码首先计算区间内所有整数的最大和,若该和小于S,则直接返回0。接着,通过两个数组smallbig分别记录从区间两端开始的连续整数和。small数组从L开始累加,big数组从R开始累加,并在最后进行反转,以便与small数组对应。最后,遍历这两个数组,判断S是否在某个连续整数和的区间内。若存在,则返回1;否则返回0。