【快手笔试题】编程题-健身

本文探讨了如何为健身者设计最优的健身路径,通过选取特定数量的锻炼方式以最大化锻炼效果值。利用排序和动态规划的方法,文章提供了一种高效的算法解决方案,并给出了Python及C语言的实现代码。

[编程题]健身

因为公司有免费健身福利,快手程序员老铁们都很爱健身,而且他们健身时像工作一样充满效率。
他们把健身过程神奇的简化了出来:健身有N种锻炼方式可选,器材可看成在一条直线上。
每种锻炼方式距门口Xi米,因为有的器材上可以支持多种锻炼方式,因此有可能出现两种锻炼方式的距离是一样的,即Xa = Xb。
老铁们一进健身房门口就开启健身形态,每走1米,就能获得1点锻炼效果值,而每种锻炼方式也有Ei的效果值,锻炼的过程就是从门口走到某种锻炼方式锻炼,然后到下一个方式锻炼,最后返回门口的过程。需要注意的是,锻炼过程中老铁们不会为了获得效果而刻意走回头路。

老铁们很想知道如果想选择某几种锻炼方式,怎样获得最大锻炼效果。

输入描述:
第一行N,表示锻炼方式的个数
第二行N个整数,表示每种锻炼方式距门口的距离
第三行N个整数,表示每种锻炼方式的效果值

输出描述:
N个整数,第k行表示选择k种锻炼方式时获得的最大锻炼效果

示例1
输入

5
1 2 3 4 5
1 1 1 1 1

输出

11
12
13
14
15

说明
对于样例第一行,老铁选择去第5种锻炼方式,考虑来回路程,一共获得5+1+5点锻炼效果值

备注:
对于所有数据,N <= 100,000,输出结果在32位整数范围内

思路:

e i ei ei是能量, d i s t dist dist是距离
要求解 m a x ( e 1 + e 2 + e 3 + … + e n ) + m a x ( d i s t ∗ 2 ) max(e1+e2+e3+…+en)+max(dist*2) max(e1+e2+e3++en)+max(dist2)
d i s t dist dist e 1 e1 e1有关,
即求解 m a x ( e 1 , e 2 , e 3 + e n − 1 ) + m a x ( e n ) + m a x ( d i s t ∗ 2 ) max(e1,e2,e3+en-1)+max(en)+max(dist*2) max(e1,e2,e3+en1)+max(en)+max(dist2)
此时可看出,前n-1个一定是val的最大值,而 m a x ( e n ) + m a x ( d i s t ∗ 2 ) max(en)+max(dist*2) max(en)+max(dist2)可以看到要么是
1. e n + d i s t ∗ 2 en+dist*2 en+dist2的和的值最大,否则
2. v a l val val最大, d i s t dist dist是前面的某个n的值。
所以应该找出前 k − 1 个 k-1个 k1最大的E,剩下的如果器材A的 d d d比前面选的 k − 1 k-1 k1个器材要大,那么最后一个器材就选A;否则,就选value第k大的器材。

用python比较容易过,这里的c的排序和查找部分我人工优化得不太好,但是思路是这样,目前用快排(粗糙版)加上简单查找可以实现80%Access

python版本100%通过:

N=int(input())
distance = input().split()
exp = input().split()
 
max_to_choose=[]
for i in range(0,N):
    info={'dist':int(distance[i]),'exp':int(exp[i])}
    max_to_choose.append(info)
max_exp=sorted(max_to_choose,key=lambda info:info['exp'],reverse=True) # 按照健身效果排序,由于排序保证是稳定的。所以健身效果相同时,距离大的在后面

max_dist=0
kmax_save=0
kmax_exp=[]
save_index=0
for i in range(0,N):
    if(i>0):
        kmax_save=kmax_save+max_exp[i-1]['exp']
        kmax_exp.append(kmax_save)
        if(max_exp[i-1]['dist']>max_dist):
            max_dist=max_exp[i-1]['dist']
    else:
        kmax_exp.append(0)
    maxval=0
    value=0
    if(save_index<=i):
        for k in range(i,N):
            value=max_exp[k]['exp']+max_exp[k]['dist']*2
            if(value>maxval):
                maxval=value
                save_index=k
    # 从剩下的里找出2d+V最大的的器材A
    if(max_dist<max_exp[save_index]['dist']):
        kmax_exp[i]=kmax_exp[i]+2*max_exp[save_index]['dist']+max_exp[save_index]['exp']
    else:
        kmax_exp[i]=kmax_exp[i]+2*max_dist+max_exp[i]['exp']
   
for km in kmax_exp:
    print(km)

c代码80%通过:

#include <stdio.h>
#include <stdlib.h>
void quick_sort(int s,int k,int a[][2])
{
    if(s<k)
    {
        int i=s,j=k;
        int tmp=a[i][0];
        int tmp2=a[i][1];
        while(i<j)
        {

            while(i<j && a[j][0]<tmp)
            {
                j--;
            }
            if(i<j)
            {
                a[i][0]=a[j][0];
                a[i][1]=a[j][1];
                i++;
            }

            while(i<j && a[i][0]>=tmp)
            {
                i++;
            }
            if(i<j)
            {
                a[j][0]=a[i][0];
                a[j][1]=a[i][1];
                j--;
            }
        }
        a[i][0]=tmp;
        a[i][1]=tmp2;
        quick_sort(s,i-1,a);
        quick_sort(i+1,k,a);
    }
}

void print(int a[][2],int p,int e)
{
    int i=0;
    for(i=p; i<=e; i++)
    {
        printf("exp:%d dist:%d\n",a[i][0],a[i][1]);
    }
    printf("\n");
}

void print_re(int kmax_exp[])
{
    int i=0;
    while(kmax_exp[i])
    {
        printf("%d\n",kmax_exp[i]);
        i++;
    }
}
int info[100000][2]= {0};
int kmax_exp[100000]= {0};
int choosed=0;

int main()
{
    int i=0,n=0;
    scanf("%d",&n);
    for(i=0; i<n; i++)
    {
        scanf("%d",&info[i][1]);
    }
    for(i=0; i<n; i++)
    {
        scanf("%d",&info[i][0]);
    }
    quick_sort(0,n-1,info); //复杂度n2
    //print(info,0,n-1);
    int k=0;
    int max_dist=0;
    int kmax_save=0;

    int save_index=-1;
    for(i=0; i<n; i++)
    {
        //先选k-1个value最大的器材
        if(i>0) //由于前k-1个始终相同,直接保存结果
        {
            kmax_save=kmax_save+info[i-1][0];
            kmax_exp[i]=kmax_save;
            choosed=i-1; //标记前i-1个为已经选择
            if(info[i-1][1]>max_dist)
            {
                max_dist=info[i-1][1];//保存最大距离
            }
        }
        //for(k=0;k<n;k++){
        //    printf("%d ",choosed[k]);
        //}
        //printf("\n");
        //print_re(kmax_exp);
        int exp=info[i][0]; //保存第k大的经验值
        int maxval=0;
        int value=0;
        //只有当en+dist*2最大的值被作为前面的
        //选择了之后才需要重新选择。从第k个开始找。
        if(save_index<=i)
        {
            for(k=i; k<n; k++)
            {
                //从剩下n-i个里面的选择一个en+dist*2最大的
                value=info[k][0]+info[k][1]*2;
                if(value>maxval)
                {
                    maxval=value;
                    save_index=k;//保存选择的这个剩下最大的器材的索引
                }
            }
        }
        //printf("maxdist:%d maxval: %d save_index:%d \n",max_dist,maxval,save_index);
        if(max_dist<info[save_index][1])
        {
            kmax_exp[i]=kmax_exp[i]+2*info[save_index][1]+info[save_index][0];
        }
        else
        {
            kmax_exp[i]=kmax_exp[i]+2*max_dist+exp;
        }
    }
    print_re(kmax_exp);
    return 0;
}

### 关于快手外包 SQL 笔试题 针对快手外包相关的 SQL 笔试题,虽然无法提供具体的题目和答案,但可以基于常见的 SQL 考察知识点来推测可能涉及的内容。以下是几个典型的 SQL 题目及其解答思路: #### 1. 数据查询与过滤 假设有一张名为 `user_activity` 的表,记录用户的活动数据,字段包括 `user_id`, `activity_date`, 和 `points_earned`。 **问题**: 查询在过去7天内获得超过100积分的用户ID列表。 ```sql SELECT DISTINCT user_id FROM user_activity WHERE activity_date >= DATE_SUB(CURDATE(), INTERVAL 7 DAY) AND points_earned > 100; ``` 此查询利用了日期函数 `DATE_SUB` 来计算过去七天的时间范围,并通过条件筛选出符合条件的用户[^2]。 #### 2. 统计分析 假设有另一张表 `video_views`,包含视频观看次数的数据,字段有 `video_id`, `view_count`, 和 `upload_date`。 **问题**: 计算每个月上传的视频总数以及平均观看量。 ```sql SELECT YEAR(upload_date) AS year, MONTH(upload_date) AS month, COUNT(video_id) AS total_videos, AVG(view_count) AS avg_view_per_video FROM video_views GROUP BY YEAR(upload_date), MONTH(upload_date); ``` 这里使用了聚合函数 `COUNT` 和 `AVG` 进行统计,并按年份和月份分组以展示每月的结果[^3]。 #### 3. 复杂连接操作 如果存在两张关联表:一张是 `users` (字段: `id`, `name`);另一张是 `orders` (字段: `order_id`, `user_id`, `amount`)。 **问题**: 找到下单金额最高的前五位客户的名字及总消费额。 ```sql SELECT u.name, SUM(o.amount) as total_spent FROM users u JOIN orders o ON u.id = o.user_id GROUP BY u.name ORDER BY total_spent DESC LIMIT 5; ``` 这段代码实现了两表之间的 JOIN 操作,并按照客户的总花费降序排列取前五个结果[^4]。 --- ### 提交简历后的等待时间差异原因探讨 关于提到的行业选择情况,在某些情况下确实会出现职位挂载现象用于未来的人力资源规划目的。这表明即使当前岗位需求不紧迫也可能接受应聘者的资料存档以便后续联系[^1]。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值