阿里笔试算法题2021

1.小强现在有n个物品,每个物品有x,y两种属性和.他想要从中挑出尽可能多的物品满足以下条件:对于任意两个物品 i 和 j ,满足( i.x < j.x 且 i.y < j.y)或者(i.x > j.x 且 i.y > j.y).问最多能挑出多少物品

  1. 第一行输入一个正整数 T.表示有T组数据.

  2. 对于每组数据,第一行输入一个正整数N.表示物品个数N.

  3. 接下来两行,每行有个N整数.

  4. 第一行表示N个节点的X属性.

  5. 第二行表示N个节点的Y属性

题解:https://blog.csdn.net/xyjy11/article/details/118032689

2.小强发现当已知xy=B以及x+y=A时,能很轻易的算出的值.但小强想请你在已知 A和B的情况下,计算出x^n+y^n的值.因为这个结果可能很大,所以所有的运算都在模1e9+7下进行.

输入例子1:
                3
                4 4 3
                2 3 4
                5 2 6
输出例子1:
                16
                999999993
                9009
import java.util.*;

public class Main{


    /**
     * 阿里2 已知 x+y=A xy = B 求x^n+y^n
     * 递推式 xn = Axn-1 - Bxn-2
     */

    static long mod = (long)Math.pow(10,9)+7;
    public static void main(String[] args) {
        Scanner in = new Scanner(System.in);
        int m = in.nextInt();
        for(int i=0;i<m;i++){
            long a = in.nextInt();
            long b = in.nextInt();
            int n = in.nextInt();
            a %= mod;
            b %= mod;
            System.out.println(solve(a,b,n));
        }
    }

    public static long solve(long a, long b,int n){
        long[] nums = new long[n+1];
        nums[1] = a;
        if(n==1) return nums[1]; //1次方直接等于A
        nums[2] = (a * a % mod - 2 * b % mod + mod) % mod;
        if(n==2) return nums[2];
        for(int i=3;i<=n;i++)
            nums[i] = ((a*nums[i-1]%mod)-(b*nums[i-2]%mod)+mod)%mod;
        return nums[n];
    }

}

主要理解当n大于3之后的递推关系;

补充:Math.pow(a,3)表示a的三次方;

3. 小强现在n有个节点,他想请你帮他计算出有多少种不同的二叉树满足节点个数为且树的高度不超过m的方案.因为答案很大,所以答案需要模上1e9+7后输出.
树的高度: 定义为所有叶子到根路径上节点个数的最大值.

例如: 当n=3,m=3时,有如下5种方案:

 动态规划题解:

import java.util.*;

public class Main{
    public static final int MOD = 1000000007;

    public static void main(String[] args) {
        Scanner in = new Scanner(System.in);
        int n = in.nextInt();
        int m = in.nextInt();
        // dp[i][j]表示i个节点最大深度为j的树数量
        long[][] dp = new long[n+1][m+1];
        Arrays.fill(dp[0], 1);
        for(int i = 1; i <= n; i++) {       //节点数
            for(int j = 1; j <= m; j++) {   //层数
                for(int k = 0; k < i; k++) {
                    // 左子树节点数为k,右子树节点数为i-k-1,且左右子树都要求小于等于j-1
                    dp[i][j] = (dp[i][j] + dp[k][j-1] * dp[i-k-1][j-1] % MOD) % MOD;
                }
            }
        }
        System.out.println(dp[n][m]);
    }
}

4.   小强想要从[1,A]中选出一个整数x,从[1,B]中选出一个整数y .使得满足x/y = a/b​的同时且x和y的乘积最大。如果不存在这样的x和y,请输出“ 0 0”.

输入描述:

输入一行包含四个整数A,B,a和b.
1≤A,B,a,b≤2e9

输出描述:

输出两个整数表示满足条件的x和y.若不存在,则输出"0 0".

例子1:

输入:1 1 2 1 输出:0 0

例子2:

输入: 1000 500 4 2 输出:1000 500

解题思路:因为a和b是自己提供的所以可以求出a b 的最大公约数c,然后将需要求解的

x初始化为a/c;y初始化为b/c;

就是x=a/c;y=a/c;然后每次x再去加上a/c,y也再去加上a/c;保证x/y=a/b成立

其中求最大公约数的算法:辗转除;

// 辗转相除法求解最大公约数
// 两个正整数a b (a>b) 的最大公约数 等于 a除以b的余数 c 和 b 之间的最大公约数
public static int GCD(int a, int b) {
    int c = 0;
    while(b != 0) {
       c = a % b;
       a = b;
       b = c;
    }
    return a;
}

完整代码

import java.util.*;
// java int 类整数的最大值是 2 的 31 次方 - 1 = 2147483648 - 1 = 2147483647
// long类型的数据范围-2的63次方 ~ 2的63次方-1,即 -9223372036854775808 ~ 9223372036854775807
public class Alibaba_4 {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        while(sc.hasNext()) {
            int A = sc.nextInt();
            int B = sc.nextInt();
            int a = sc.nextInt();
            int b = sc.nextInt();

            // 首先求解a与b的最大公约数 Greatest Common Divisor(GCD)
            int c = GCD(a, b);
            // System.out.println(c);

            // 相当于约分处理,简化
            a = a / c;
            b = b / c;

            long x, y;
            // 判断是否存在x、y
            if(A < a || B < b) {
                x = 0;
                y = 0;
            }else {
                x = a;
                y = b;
                while(x + a <= A && y + b <= B) {
                    x += a;
                    y += b;
                }
            }
            System.out.println(x+" "+y);
        }
        sc.close();
    }
    // 辗转相除法求解最大公约数
    // 两个正整数a b (a>b) 的最大公约数 等于 a除以b的余数 c 和 b 之间的最大公约数
    public static int GCD(int a, int b) {
        int c = 0;
        while(b != 0) {
            c = a % b;
            a = b;
            b = c;
        }
        return a;
    }
}

5.在一张2D地图上小强有n座房子,因为地理位置的原因没有办法给每座房子提供水源,所以小强打算修建一条平行y轴的水渠。因为这条水渠无限长,所以能够看做是一条平行于y轴的直线。现在小强想确定修建水渠的位置,能够使得这n座房子到水渠的垂直距离和最小,请你输出最小的距离和。

输入描述:

第一行输入一个正整数n.

接下来n行,每行输入两个正整数xi,yi,分别表示每个房子所在的二维坐标.

1000000≤xi,yi≤100000

1≤n≤100000

输出描述:

输出一个整数表示答案

解题思路:因为水渠平行于y轴所以只需要找出所有xi的中位数即可。然后所有xi-中位数之和就是结果。

import java.util.Arrays;
import java.util.Comparator;
import java.util.Scanner;

public class Alibaba_5 {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        int n = sc.nextInt(); //房子数目
        int[][] house = new int [n][2];
        for (int i = 0; i < n; i++) {
            house[i][0] = sc.nextInt();
            house[i][1] = sc.nextInt(); // 也可以不读入这个数据
        }

        Arrays.sort(house, new Comparator<int[]>() {
            @Override
            public int compare(int[] o1, int[] o2) {
                return o1[0] - o2[0];
            }
        });

        // 存放距离,注意数据溢出
        long res = 0;
        // 求解中位数,作为水渠的位置
        double mid_location = n % 2 == 1? house[(n-1)/2][0]: (house[n/2 - 1][0] + house[n/2][0]) / 2;

        //求解距离和
        for(int i = 0; i < n; i ++) {
            res += Math.abs(house[i][0] - mid_location);
        }
        System.out.println(res);
    }
}

6.最近小强主办了一场国际交流会,大家在会上以一个圆桌围坐在一起。由于大会的目的就是让不同国家的人感受一下不同的异域气息,为了更好地达到这个目的,小强希望最大化邻座两人之间的差异程度和。为此,他找到了你,希望你能给他安排一下座位,达到邻座之间的差异之和最大。

输入描述:

输入总共两行。
    第一行一个正整数n,代表参加国际交流会的人数(即圆桌上所坐的总人数,不单独对牛牛进行区分)
    第二行包含n个正整数,第i个正整数ai代表第i个人的特征值。
    其中3 ≤ n ≤ 10^5, 1 ≤ ai ≤ 10^9 (注意数据溢出)
 注意:邻座的定义为: 第i人(1<i<n)的邻座为i-1,i+1,第1人的邻座是2,n,第n人的邻座是1,n-1。
    邻座i,j的差异值计算方法为|ai-aj|。
    每对邻座差异值只计算一次。


输出描述:

    输出总共两行。
    第一行输出最大的差异值。
    第二行输出用空格隔开的n个数,为重新排列过的特征值。(注意:不输出编号)
    如果最大差异值情况下有多组解,输出任意一组即可。

输入
4
3 6 2 9
输出
20
6 2 9 3
说明
这么做的话,差异和为|6−2∣+∣2−9∣+∣9−3∣+∣3−6∣= 20为最大的情况。

解题思路:

大体思路:数组排序,计算数组前后(0,n-1)+(1,n-2).....

        将数组排序,新建resultArr存储最终结果。定义left和right指定到排序后的左和右。循环排序后的数组,通过i%2==0来判断是left放进还是right放进去,然后计算数组前后中前后差值。循环结束加上最后一位到头位置的差值(环)就为总和。

import java.util.Arrays;
import java.util.Comparator;
import java.util.Scanner;

public class Alibaba_6 {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        int n = sc.nextInt(); //人数
        long[] terms = new long[n];
        for (int i = 0; i < n; i++){
            terms[i] = sc.nextInt(); //特征值
        }
        Arrays.sort(terms);

        // 声明一个输出空间
        long[] resultArr = new long[n];
        long reslutSum = 0;

        int left = 0;
        int right = n - 1;
        for (int i = 0; i < n; i++){
            if(i%2==0){
                resultArr[i] = terms[left];
                left++;
            }else {
                resultArr[i] = terms[right];
                right--;
            }

            if(i>0) reslutSum = reslutSum + Math.abs(resultArr[i]-resultArr[i-1]);
        }
        //计算最后一位与第一位的差值
        reslutSum = reslutSum + Math.abs(resultArr[n-1]-resultArr[0]);

        //输出结果
        System.out.println(reslutSum);
        for (long result : resultArr) {
            System.out.print(result + " ");
        }
    }
}


 

  • 5
    点赞
  • 31
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
阿里社招推荐和NLP算法工程师的笔试中可能会出现的算法有很多种,我将为你提供一个例子进行回答。 假设目要求设计一个基于协同过滤的电影推荐系统,根据用户的历史观影记录,为用户推荐其可能喜欢的电影。 首先,我们需要建立一个电影评分矩阵。矩阵的行表示用户,列表示电影,每个位置的值表示用户对该电影的评分。该评分矩阵可以通过采集用户行为数据和问卷调查的方式得到。 接下来,我们需要计算用户之间的相似度,然后为用户推荐那些和他们之前喜欢的电影相似的电影。常用的相似度计算方法有余弦相似度和皮尔逊相关系数。 具体算法步骤如下: 1. 对于一个指定用户,找到与其有相似观影记录的其他用户。 2. 根据这些相似用户的观影记录,计算推荐列表。 3. 根据推荐列表和已观看的电影,为该用户生成最终的推荐结果。 这个算法主要考察了协同过滤算法的应用,以及相似度计算的方法。同时,对于大规模的数据集,还可能需要考虑算法的优化和并行化处理。 总结起来,阿里社招推荐和NLP算法工程师笔试中的算法目涉及多种多样的问,需要候选人具备扎实的算法和数据结构基础,对相关领域的理论和实践有深入的了解,并能够灵活应用所学知识解决实际问。编程能力和思维的严密性也是评估的重要因素。
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值