字节跳动笔试第三题(2020年4月12日)

题目:一个人想买m件衣服,这时候他有n张优惠卷,只有衣服的价格>=优惠卷时,才可以使用,而且优惠卷可以重复使用。求问花的钱最少是多少。
输入:第一行,n,m代表优惠卷的个数、衣服的个数
第二行代表优惠卷的金额
第三行代表衣服的金额
例:
3 4
50 100 200
99 199 200 300
输出248

暴力法的话:O(n^2),怎么优化?O(nlogn)(假设n==m)
整道题的思路:
使用的是贪心算法+二分搜索
如果想要money最小,那么每件衣服的花费就应该是最小,那么使用的优惠卷应该是最接近或者等于衣服价格的。对优惠卷排序后,使用二分法的话,应该找最后一个小于衣服价格的数。
整个时间复杂度为mlogn,空间复杂度为O(n)

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

public class Main {
	public static int binarySearch(int[] arr, int target) {
		int low = 0, high = arr.length-1;
		int id = -1;
		
		// 要找最后一个比target小的数
		while(low <= high) {
			int mid = low + (high - low)/2;
			if (arr[mid] <= target) {
				int tmp = mid;
				while(tmp < arr.length-1 && arr[++tmp] <= target ) {}
				if (arr[tmp] <= target) {
					id = arr.length-1;
				} else {
					id = tmp - 1;
				}
				return id;
			}else {
				high = mid - 1;
			}
		}
		return id;
		
	}

	public static void main(String[] args) {
		Scanner in = new Scanner(System.in);

		// n张优惠卷
		int n = in.nextInt();
		// m件物品
		int m = in.nextInt();	
		int[] sale = new int[n];
	
		for(int i = 0; i < n; i++) {
			sale[i] = in.nextInt();
		}
		// 对n张优惠卷进行从小到大排序
		Arrays.sort(sale);
		
		// 避免溢出
		long money = 0l;
		// 存储输入的物品的价格\对应的优惠卷id
		int target = 0, id = 0;
		// m件物品的价格
		for(int i = 0; i < m; i++) {
			target = in.nextInt();
			id = binarySearch(sale, target);
			if (id != -1) {
				money += (target - sale[id]);
			}else {
				money += target;
			}
		}
		System.out.println(money);
	}

}

你可能感兴趣的:(笔试,面试题)