拼多多2020春招4月笔试编程题(java)

1.1 第一题

第一次拼团活动后,多多鸡收到了用户非常不错的反馈。于是,多多鸡又准备举办第二次优惠活动,这次的规则是:买三送一!即每购买3个商品,免费赠送其中价格最低的一个。
皮皮虾现在打算购买 N 个商品(编号 1~N),其中第 i 个商品的价格为 Ai。
现在皮皮虾需要的你帮忙找到一种购买策略,是的能够花费最少的钱买到所有的商品。

1.2 输入输出描述

输入描述:

共两行,第一行 1 个整数 N,表示皮皮虾准备购买的商品数量。
(1 <= N <= 100,000)
第二行 N 个整数 Ai,分别表示 N 个商品的价格。
(1 <= Ai <= 1,000,000)

输出描述:

共一行,1 个整数,表示皮皮虾购买 N 个物品最少花费多少钱。

示例:

输入
4
100 200 300 400
输出
800
说明
一种可能的方案:分两次购买;
第一次购买价格 200,300,400 的商品,满足买三送一,价格 200 的商品免费赠送,花费:300 + 400 = 700;
第二次购买价格 100,由于不够 3 个商品,无法享受优惠,花费:100
一共花费:700 + 100 = 800。

1.3.1 方案一(升序)

import java.util.Arrays;
import java.util.Scanner;
public class Test {
    public static void main(String[] args) {
    	//得到输入
        Scanner in = new Scanner(System.in);
        int N = in.nextInt(); //第一行,商品个数
        int[] A = new int[N]; 
        for(int i = 0; i < N; i++){
            A[i] = in.nextInt(); //第二行,商品价格
        }
        long res = 0; //花钱总和,int不够放,所以改用long
        Arrays.sort(A); //价格排序,升序
        int times = N/3; //买三送一的次数
        for(int i = 0; i < times; i++){ 
            int index = 0;
            while(index < 2){ //从后往前累加,去掉赠送的第三个
                res += A[N - 3*i - 1 - index]; 
                index++;
            }
        }
        int remain = N % 3; //将不能参与优惠的商品加入
        while(remain > 0){
            res += A[remain-1];
            remain--;
        }
        System.out.println(res); //打印结果
    }
}

1.3.2 方案二(降序)

将 Arrays.sort() 升序排序改为降序,可以让代码更优美,自定义 compare() 可以参考这位博主的解析:eyckwu: Comparator源码解析

import java.util.Arrays;
import java.util.Comparator;
import java.util.Scanner;
public class Test{
    public static void main(String[] args) {
    		//得到输入
        Scanner in = new Scanner(System.in);
        int N = in.nextInt(); //第一行,商品个数
        Integer[] A = new Integer[N]; 
        for(int i = 0; i < N; i++)
            A[i] = in.nextInt(); //第二行,商品价格
        NumberCompare nCompare = new NumberCompare();
        Arrays.sort(A, nCompare); //首先排序,降序
        long res = 0; //花钱总和
        for(int i = 0; i < N; i++){ 
        		if(A[i] % 3 != 2) //余数为2可以优惠
        			res += A[i];
        }
        System.out.println(res); //打印结果
    }
}
class NumberCompare implements Comparator<Integer>{
	@Override
	public int compare(Integer o1, Integer o2) {
		return o1 > o2 ? -1 : (o1 == o2 ? 0 : 1);
	}
}

2.1 第二题

leetcode974:和可被K整除的子数组

多多路上从左到右有 N 棵树(编号 1~N),其中第 i 棵树有和谐值 Ai。
多多鸡认为,如果一段连续的树,它们的和谐值之和可以被 M 整除,那么这个区间整体看起来是和谐的。
现在多多鸡想请你帮忙计算以下,满足和谐条件的区间的数量。

2.2 输入输出描述

输入描述:

第一行,有 2 个整数 N 和 M,表示树的数量以及计算和谐值的参数。
(1 <= N <= 100,000,1 <= M <= 100)
第二行,有 N 个整数 Ai,分别表示第 i 棵树的和谐值。
(0 <= Ai <= 1,000,000,000)

输出描述:

共一行,每行1个整数,表示满足整体是和谐的区间的数量。

示例:

输入
5 2
1 2 3 4 5
输出
6
说明
长度为1:[2], [4]
长度为2:无
长度为3:[1,2,3], [3,4,5]
长度为4:[1,2,3,4], [2,3,4,5]
长度为5:无
共 6 个区间的和谐值之和可以被 2 整除。

备注:

对于 50% 的数据,有 N<=1,000
对于 100%的数据,有 N<=100,00

2.3.1 前缀和方法

时间复杂度:O(N2)
空间复杂度:O(N)
时间复杂度过高,达不到要求。

import java.util.Scanner;
public class Test {
	public static void main(String[] args) {
		Scanner in = new Scanner(System.in);
		int N = in.nextInt(); //树数量
		int M = in.nextInt(); //M
		int[] A = new int[N];  //树的和谐值
		for(int i = 0; i < N; i++)
			A[i] = in.nextInt();
		System.out.println(prefix(A,N,M));
	}
	//前缀和方法
	public static int prefix(int[] a, int n, int m) {
		if(n == 0)
			return 0;
		else {
			//构建前缀和数组
			int[] sum = new int[n+1]; 
			for(int i = 0; i < n; i++) {
				sum[i+1] = sum[i] + a[i];
			}
			//依次判断余数是否为0
			int res = 0; //结果
			for(int i = 0; i < n; i++) {
				for(int j = i+1; j < n+1; j++) {
					if((sum[j] - sum[i]) % m == 0) res++;
				}
			}
			return res;
		}
	}
}

2.3.2 前缀和+哈希表

时间复杂度:O(N)
空间复杂度:O(M)

public int hashTable(int[] a, int n, int m) {
		int sum = 0, res = 0;
		int[] map = new int[m]; //创建哈希表
		map[0] = 1; //重要
		for(int i = 1; i <= n; i++) { 
			sum = sum + a[i-1];
			int key = ((sum % m) + m) % m;  //防止负数
			res += map[key]; 
			map[key]++;
		}
		return res;
	}
  1. map[0] 之所以要初始化为1,是因为sum数组中 % m = 0 的数的特殊性,这些数必须可以单独作为子数组计算到结果中,这和余数不为0的数不一样,若没有这个初始化操作,结果中会漏掉单独子数组。
  2. map[0] = 1,可以解释为在sum数组的前面加一个 0(或 m),从而将原本数组中余数为0的数与之关联,计算到结果中,多出来的这部分计算结果正好填补了上面提到的缺失的单独子数组。

3.1 第三题

第三题题干

未完待续

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值