华为OD算法

做甜点需要购买配料,目前共有n种基料和m种配料可供选购 制作甜点需要遵循以下几条规则: 必须选择1种基料;可以添加0种、1种或多种配料,每种类型的配料最多添加2份 给定长度为n的数组base, base[i]表示第i种基料的价格 给定长度为m的数组topping, topping[j]表示第j种配料的价格 给定一个正数target,表示你做的甜点最终的价格要尽量接近这个数值 返回最接近这个数值的价格是多少 如果有多个方案,都最接近target,返回价格最小的那个答案 1 <= n,m <= 10 1 <= base[i], topping[j] <= 10 ^ 4 1 <= target <= 10 ^ 4

题目解析 :

1.做一份甜点=1种基料+n种配料(每种配料只能加0份,1份或者2份),base[i]表示第i种基料的价格,
给定长度为m的数组topping, topping[j]表示第j种配料的价格;
2. 选出一种甜品方案,它需要的钱最接近给出的加个target,如果有多个方案,都最接近target,返回价格最小的那个价格(譬如tareget是100,一种方案95,一种方案105,选95的方案)。
3. 因为m<=10,所以配料最多只有10种,每种只能加0份,1份或者2份,所以配料的价格最多就3^10个方案,i<=n,可以直接暴力解决,
4. target-基料base[i]=rest,从配料的3^10个方案里面选择一个最接近rest的方案a+base[i]=cur;记录下来。
5. 循环基料base,看哪一个cur最接近target,并且最少,记录成ans输出。

public class DessertPriceClosedTarget {

	// 方法1,用有序表的方法
	public static int closedTarget1(int[] base, int[] topping, int target) {
		// 辅料所能产生的所有价格!
		// 0 5 15 23
		TreeSet<Integer> set = new TreeSet<>();
		// 暴力展开!收集所有能产生的价格!放入辅料表里去!
		process1(topping, 0, 0, set);
		int ans = Integer.MAX_VALUE;
		for (int num : base) {
			// 枚举每一种主料的价格!
			// 最终能搭配出来的最接近的价格
			int cur = num;
			// 20   100
			// 110  100
			if (num < target) { // cur < 要求
				// 60  100
				// 40
				int rest = target - num;
				// <= rest 最接近的!
				Integer floor = set.floor(rest);
				// >= rest 最接近的!
				Integer ceiling = set.ceiling(rest);
				if (floor == null || ceiling == null) {
					cur += floor == null ? ceiling : floor;
				} else {
					cur += rest - floor <= ceiling - rest ? floor : ceiling;
				}
				// cur会选择floor,或ceiling,谁加上最接近target选谁!
			}
			if (Math.abs(cur - target) < Math.abs(ans - target)
					|| (Math.abs(cur - target) == Math.abs(ans - target) && cur < ans)) {
				ans = cur;
			}
		}
		return ans;
	}

	// 暴力展开!收集所有能产生的价格!放入辅料表里去!
	// topping[index....] 
	// topping[0...index-1]  sum
	public static void process1(int[] topping, int index, int sum, TreeSet<Integer> set) {
		if (index == topping.length) {
			set.add(sum);
		} else {
			process1(topping, index + 1, sum, set);
			process1(topping, index + 1, sum + topping[index], set);
			process1(topping, index + 1, sum + (topping[index] << 1), set);
		}
	}

	// 方法2,用数组排序+二分的方法

	public static int[] collect = new int[14348907];

	public static int size = 0;

	public static int closedTarget2(int[] base, int[] topping, int target) {
		size = 0;
		process2(topping, 0, 0);
		Arrays.sort(collect, 0, size);
		int ans = Integer.MAX_VALUE;
		for (int num : base) {
			int cur = num;
			if (num < target) {
				int rest = target - num;
				int floor = floor(rest);
				int ceiling = ceiling(rest);
				if (floor == -1 || ceiling == -1) {
					cur += floor == -1 ? ceiling : floor;
				} else {
					cur += rest - floor <= ceiling - rest ? floor : ceiling;
				}
			}
			if (Math.abs(cur - target) < Math.abs(ans - target)
					|| (Math.abs(cur - target) == Math.abs(ans - target) && cur < ans)) {
				ans = cur;
			}
		}
		return ans;
	}

	public static void process2(int[] topping, int index, int sum) {
		if (index == topping.length) {
			collect[size++] = sum;
		} else {
			process2(topping, index + 1, sum);
			process2(topping, index + 1, sum + topping[index]);
			process2(topping, index + 1, sum + (topping[index] << 1));
		}
	}

	public static int floor(int num) {
		int l = 0;
		int r = size - 1;
		int m = 0;
		int ans = -1;
		while (l <= r) {
			m = (l + r) / 2;
			if (collect[m] <= num) {
				ans = collect[m];
				l = m + 1;
			} else {
				r = m - 1;
			}
		}
		return ans;
	}

	public static int ceiling(int num) {
		int l = 0;
		int r = size - 1;
		int m = 0;
		int ans = -1;
		while (l <= r) {
			m = (l + r) / 2;
			if (collect[m] >= num) {
				ans = collect[m];
				r = m - 1;
			} else {
				l = m + 1;
			}
		}
		return ans;
	}

	// 为了验证
	public static int[] randomArray(int n, int v) {
		int[] arr = new int[n];
		for (int i = 0; i < n; i++) {
			arr[i] = (int) (Math.random() * v) + 1;
		}
		return arr;
	}

	// 为了验证
	public static void main(String[] args) {
		int N = 8;
		int V = 10000;
		int testTime = 5000;
		System.out.println("功能测试开始");
		for (int i = 0; i < testTime; i++) {
			int n = (int) (Math.random() * N) + 1;
			int m = (int) (Math.random() * N) + 1;
			int[] base = randomArray(n, V);
			int[] topping = randomArray(m, V);
			int target = (int) (Math.random() * V) + 1;
			int ans1 = closedTarget1(base, topping, target);
			int ans2 = closedTarget2(base, topping, target);
			if (ans1 != ans2) {
				System.out.println("出错了!");
			}
		}
		System.out.println("功能测试结束");

		System.out.println("性能测试开始");
		int n = 15;
		int m = 15;
		int[] base = randomArray(n, V);
		int[] topping = randomArray(m, V);
		int target = (int) (Math.random() * V) + 1;
		System.out.println("base数组长度 : " + n);
		System.out.println("topping数组长度 : " + m);
		System.out.println("数值范围 : " + V);
		long start = System.currentTimeMillis();
		closedTarget2(base, topping, target);
		long end = System.currentTimeMillis();
		System.out.println("运行时间 : " + (end - start) + " 毫秒");
		System.out.println("性能测试结束");

	}

}
  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
智能驾驶是指利用人工智能和相关技术驱动汽车,使其具备感知、决策和行动的能力,实现自动驾驶。华为OD算法题中的智能驾驶问题,可以分为三个方面进行回答。 首先是感知能力。智能驾驶首先需要能够感知周围的环境和交通状况。华为OD算法可能会涉及到对摄像头和雷达等感知装置的数据进行处理和分析,提取出道路、车辆、行人、交通信号等信息。通过深度学习等技术,可以对感知数据进行实时识别和分类,从而实现对行驶环境的感知。 其次是决策能力。基于感知数据和相关规则,智能驾驶还需要具备决策的能力,即在不同的道路情况下,能够做出合理的行驶决策。华为OD算法题中可能会涉及到对不同情况下的决策策略进行建模和优化,如车辆的换道、超车、减速等。 最后是行动能力。智能驾驶需要将决策结果转化为实际的行动,即控制汽车进行驾驶操作。华为OD算法题中可能会涉及到对车辆的加速、转向、制动等操作进行控制。各个操作的控制需要精确而稳定的算法控制策略,确保车辆的稳定和安全。 总结起来,华为OD算法题中的智能驾驶问题涉及到感知、决策和行动三个方面的技术和算法。通过对感知数据的处理和分析,决策策略的建模和优化,以及行动的控制和操作,实现车辆的自动驾驶。这将为交通运输带来更高效、更安全和更环保的未来。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值