京东Android第二题:神奇数

题目描述

给出一个区间[a, b],计算区间内“神奇数”的个数。

神奇数的定义:如果一个数的数字组合可以分成两部分A,B,如果A部分之和等于B部分之和,则这个数是一个神奇数。

比如:242,存在[2,2]和[4],2 + 2 = 4,则242是神奇数。

输入描述:

输入为两个整数a和b,代表[a, b]区间

输出描述:

输出为一个整数,表示区间内满足条件的整数个数

输入例子:

1 50

输出例子:

4

题目解析:

神奇数的定义是,对于每一个这样的数,都可以将组成这个数的数字序列,分成A,B两个部分,A部分的和等于B部分的和,则可以得出整个数的数字序列的和’Sum = A + B = 2B’,没错,2B即代表Sum必然是一个偶数,之后我们考虑整个数字序列分为两个集合,每个数字元素都存在两种情况,在A集合或者不在A集合,所以可以分为2^n种情况,n为数字元素的个数,同时由于我们并不关注A和B的集合的有序性,比如一种情况为[2,2]或[4],另一种情况为[4]或[2,2],这里我们视为是同一种情况。所以经过分析得出,我们只需要分析的情况为 2^n / 2,考虑到每一个元素都有两种情况,我们可以用1代表存在于A集合,0代表不存在于A集合,那么当我们对每个元素的情况做一个排列,可以得到’101…10’这样一个二进制序列,而我们可以将其转化为一个整数,从而进行循环。

代码:


import java.util.ArrayList;
import java.util.List;
import java.util.Scanner;

/**
 * Created by nocla on 2017/9/8.
 */
public class Algorithm_01 {
    public static boolean check(int a){
        List<Integer> numbers = new ArrayList<>();
        int sum = 0;
        while (a != 0){
            numbers.add(a % 10);
            sum += a % 10;
            a /= 10;
        }
        if (sum % 2 != 0){
          //如果sum为奇数,则直接返回false
            return false;
        }
        for (int i = ((int) Math.pow(2, numbers.size())) / 2; i > 0; i--) {
            int temp = 1;
          //利用temp遍历每种情况的每个元素
          //1011 & 0001即遍历第一个元素的情况
            int sumA = 0;
            for (int j = 0; j < numbers.size(); j++) {
                if ((i & temp) == 0){
                    sumA += numbers.get(j);
                }
                if (sumA > sum / 2){
                    break;
                }
                temp = temp << 1;
            }
            if (sumA == sum / 2){
                return true;
            }
        }
        return false;
    }

    public static void main(String[] args) {
        // TODO Auto-generated method stub
        Scanner in = new Scanner(System.in);
        int start = in.nextInt();
        int end = in.nextInt();
        int cnt = 0;
        for ( int i = start ; i <= end ; i++){
            if (check(i)){
                cnt++;
            }
        }
        System.out.println(cnt);
        in.close();
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值