京东2018秋招编程题

C++开发工程师 京东 2018秋招编程题 (代码后续更新。。。)


1、神奇数

将一个数n的各数位分成两部分,两部分之和相等,则称这个数为神奇数。比如242分成[2,2]、[4]。输入一个范围[l, r],输出这个范围内神奇数的个数。

示例:

输入:
1,50
输出:
4

解析:

判断一个数是否是神奇数,首先应该获取其各个数位{a1, a2, a3, a4, …},按照神奇数的定义,需要将数位分成两部分,且两部分元素和相等,因此所有数位的和sum{a1, a2, a3, a4, …}必为偶数。如果不是偶数,则必然不是神奇数

因此,这个问题就演变成,在{a1, a2, a3, a4, …}中寻找一个子集,使得sum{子集} = sum/2

显然,这是一个0-1背包问题。可以用回溯法、动态规划
这里使用动态规划,用dp[i][j]表示子数组{a1, a2, a3, a4,…, ai}的元素和是否等于j
初始dp[i][0] = true (所有元素都不选,和为j)
如果不选择第i个元素,则dp[i][j] = dp[i-1][j]
如果选择第i个元素,则dp[i][j] = dp[i-1][j-num[i]]
因此,dp[i][j] = dp[i-1][j] || dp[i-1][j-num[i]]
dp[n][newSum]即表示是否可以找到一个子集,其元素和为sum/2。

C++代码实现

#include <iostream>
#include <vector>
using namespace std;
int l=0,r=0;

//动态规划
bool canPartition(vector<int>&dicts,int n,int sum)
{
    vector<vector<bool>> dp(n+1,vector<bool>(sum+1,false));
    for(int i=0; i<=n; i++)
        dp[i][0] = true;
    for(int j=1; j<=sum; j++){
        for(int i=1; i<=n; i++){
            dp[i][j] = dp[i-1][j]; //不选第i个元素
            if(j>=dicts[i-1])      //选第i个元素
                dp[i][j] = dp[i][j] || dp[i-1][j-dicts[i-1]];
        }
    }
    return dp[n][sum];
}

bool isSqs(int num)
{
    vector<int> dicts(10,0);
    int k=0,sum=0;
    while(num!=0){
        dicts[k++] = num%10;
        num /= 10;
        sum += dicts[k-1];
    }
    if(sum & 1)
        return false;
    return canPartition(dicts,k,sum>>1);
}

int sqs()
{
    if(r<11)
        return 0;
    if(r==11)
        return 1;
    int cnt = 1;
    for(int i=12; i<=r; i++){
        if(isSqs(i))
            cnt++;
    }
    return cnt;
}

int main()
{
    cin>>l>>r;
    cout<<sqs();
    return 0;
}

2、疯狂的数列

有一个无限数列,{1,2,2,3,3,3,4,4,4,4,…},数字n在数列中出现n次,且是连续的。输入一个整数n,输出第n项数字。n的范围为[1,10^18]。

示例:

输入:
169
输出:
18

解析:

用dp[i]表示数字i在无限数列的索引,则有:
dp[1] = 1
dp[2] = 3
dp[3] = 6
dp[4] = 10
dp[5] = 15

dp[n] = n*(n+1)/2
因此判断第n项的数字,应该找到dp[i]<= n <=dp[i+1],
这里的i 或者 i+1 即为结果。

C++代码实现
下面这个代码会超时。

int getIndex(long long& n)
{
    if(n==1)
        return 1;
    long long sum = 0,last = 1;
    for(int i=sqrt(n); i<n && sum<=n; i++){
        sum = ((i+1)*i)>>1;
        if(sum==n)
            return i;
        else if(sum < n)
            last = i;
    }
    return last+1;
}

int main()
{
    long long n;
    cin>>n;
    cout<<getIndex(n);
    return 0;
}

猜你喜欢

转载自blog.csdn.net/peaktravel/article/details/77899156
今日推荐