pdd笔试20190728

前言:

拼多多的笔试题对我来讲比较难,参考牛客大佬的题解,自己开始预习题目中涉及的知识点吧

作者:Sss201903111816437
链接:https://www.nowcoder.com/discuss/212692
来源:牛客网

One:几乎严格升序

2.回溯

Two:首尾相连的一组字符串(回溯)

Three: 多任务的执行顺序(贪心+拓扑)

题目:现在一共有N个待执行的任务,每个任务需要Pi的时间完成执行。同时任务之间可能会有一些依赖关系,比如任务1可能依赖任务2和任务3,那么任务1必须等任务2和任务3执行完成后才能开始执行。为了最小化任务的平均返回时长,请安排所有任务的执行顺序。假设在零时刻,所有N个任务已到达系统。

思路:贪心(每次先将不依赖其他任务的任务按从小到大的顺序执行) 借助优先队列(堆)BFS

  • 构建图 map<顶点,依赖的顶点>,同时更新每个顶点的入度(该顶点依赖其他的顶点的个数,比如执行任务5,需要先执行任务1,2,3,则任务5的入度为3),不依赖其他顶点的顶点的度为0

  • BFS,入度为0的顶点先进堆,依次弹出的同时,更新依赖该顶点的所有顶点的入度(该顶点不在图中了,被依赖的顶点的度-1),更新后符合入度=0的顶点入堆

public class Main3 {
	/**
	 * 题目:一共有N个待执行的任务,每个任务需要Pi时间,任务之间有依赖,求完成任务的平均时间最短 思路:拓扑排序 +
	 * 贪心(每次先将不依赖其他任务的任务按从小到大的顺序执行) 借助优先队列(堆)BFS 1.构建图 map<顶点,依赖的顶点>
	 * 同时更新每个顶点的入度(该顶点依赖其他的顶点的个数,比如执行任务5,需要先执行任务1,2,3,则任务5的入度为3),不依赖其他顶点的顶点的度为0
	 * 2.BFS,入度为0的顶点先进堆,依次弹出的同时,更新依赖该顶点的所有顶点的入度(该顶点不在图中了,被依赖的顶点的度-1),更新后符合入度=0的顶点入堆
	 */
	static class Task {
		int seq;
		int time;

		public Task(int seq, int time) {
			this.seq = seq;
			this.time = time;
		}
	}

	public static void main(String[] args) {
		Scanner in = new Scanner(System.in);
		int n = in.nextInt();
		int m = in.nextInt();
		Task[] tasks = new Task[n + 1];
		for (int i = 1; i <= n; i++) {
			tasks[i] = new Task(i, in.nextInt());
		}
		// 1.构建图
		HashMap<Integer, List<Integer>> graph = new HashMap<>();
		int[] degree = new int[n + 1];
		for (int i = 1; i <= n; i++) {
			int x = in.nextInt();
			int y = in.nextInt();
			if (graph.containsKey(x)) {
				graph.get(x).add(y);
			} else {
				List<Integer> edge = new ArrayList<Integer>();
				edge.add(y);
				graph.put(x, edge);
			}
			degree[y]++;
		}

		ArrayList<Integer> res = mutilTaskSeq(graph, degree, tasks);

		for (int i = 0; i < n; i++) {
			System.out.print(res.get(i));
			if (i != n - 1) {
				System.out.print(" ");
			}
		}
	}

	public static ArrayList<Integer> mutilTaskSeq(HashMap<Integer, List<Integer>> graph, int[] degree, Task[] tasks) {
		ArrayList<Integer> res = new ArrayList<>();

		PriorityQueue<Task> queue = new PriorityQueue<>(new Comparator<Task>() {
			@Override
			public int compare(Task t1, Task t2) {
				return t1.time - t2.time;
			}
		}); // 按对象指定属性的大小排序

		// 2.入堆,按贪心排序
		for (int i = 1; i < tasks.length; i++) { // 从任务1开始
			if (degree[i] == 0) {
				queue.offer(tasks[i]);
			}
		}
		// 3.BFS
		while (!queue.isEmpty()) {
			Task point = queue.poll();
			res.add(point.seq);
			if (graph.containsKey(point.seq)) {
				List<Integer> edges = graph.get(point.seq);
				for (Integer edge : edges) {
					if (--degree[edge] == 0) {
						queue.offer(tasks[edge]);
					}
				}
			}
		}
		return res;
	}
}

输入样例:
5(任务个数) 6(任务间依赖的个数)
1 2 1 1 1 (各个任务执行的时间)
1 2 (任务2 依赖任务1)
1 3 …
1 4
2 5
3 5
4 5

输出样例
1 3 4 2 5

Four: 搭积木(动态规划)

题目:有N个长方体积木, 每个积木的高都是1,长宽都为Li,重量为Wi。现在想要用这些积木搭一个高高的金字塔,每一层由且仅由一块积木组成,同时每一层积木的边长都比下方的积木小,每块积木智能承受自身重量的7倍重量,请计算最高可以搭一个多高的金字塔?

思路:动态规划

  • 准备工作:将积木长度从小到大排序,如果长度相等,质量小的排在前面
  • dp[N][2]保存以第N块积木为底
  • dp[i][0]: 以第N块积木为底,积木能搭建的最大高度
  • dp[i][1]: 以第N块积木为底,达到最大高度时,第N块积木承受的重量(放在第N块上的所有积木的和)
  • 从长度最小的积木开始,初始值dp[0][0]=1,dp[0][1]=最小积木的重量
    • 每次只需考虑最下面的一块积木能否满足积木严格大于次下面且上面的所有积木重量和不超过自身重量7倍的条件的最大
    • 维护一个当前木块之前为底的所有积木能到达的最大高度变量,和达到此最大高度所在的第x块积木
    • dp[i][0] =从[0,i-1]为底的积木中选择符合条件的积木x,其达到的最大高为dp[x][0] + 1, 当前所有积木的重量为dp[i][1] = dp[x] + 第i块积木的重量
import java.util.*;
/**
 * @author jinhuajian
 * @data 2019年7月30日---下午12:02:14
 * @blog https://me.csdn.net/qq_37119939
 */
public class Main4 {
	static class Box {
		int width;
		int weight;
		public Box(int i, int j) {
			width = i;
			weight = j;
		}
	}
	public static void main(String[] args) {
		Scanner in = new Scanner(System.in);
		int n = in.nextInt();
		Box[] boxs = new Box[n];
		for (int i = 0; i < n * 2; i++) {
			if (i < n) {
				Box box = new Box(in.nextInt(), -1);
				boxs[i] = box;
			} else {
				boxs[i - n].weight = in.nextInt();
			}
		}
		/*
		 * Arrays.sort(boxs, new Comparator() {
		 * 
		 * @Override public int compare(Box b1, Box b2) { //
		 * 按宽度从小到达排序,若一样宽,更轻的排在前面,用轻的(这里贪心,轻的给后面的负担小,但是自己能承受的也小了) return b1.width ==
		 * b2.width ? b1.weight - b2.weight : b1.width - b2.width; } });
		 */
		Arrays.sort(boxs, (b1, b2) -> {
			return b1.width == b2.width ? b1.weight - b2.weight : b1.width - b2.width;
		});
		int[][] dp = new int[n][2];
		dp[0][0] = 1;
		dp[0][1] = boxs[0].weight;
		int maxHeight = 0;
		for (int i = 1; i < n; i++) {
			int preMaxHeight = 0;// 容易出错,以i为底之前的积木高初始化为0
			int totalWeight = 0;
			for (int j = i - 1; j >= 0; j--) {
				if (boxs[i].width > boxs[j].width && boxs[i].weight * 7 >= dp[j][1]) {
					if (dp[j][0] > preMaxHeight) { // 以前的高至少为1
						preMaxHeight = dp[j][0];
						totalWeight = dp[j][1];
					}
				}
			}
			dp[i][0] = preMaxHeight + 1;
			maxHeight = Math.max(maxHeight, dp[i][0]);
			dp[i][1] = totalWeight + boxs[i].weight;
		}
		System.out.println(maxHeight);
	}
}

测试用例:
输入:
10
1 2 3 4 5 6 7 8 9 10
1 1 1 1 1 1 1 1 1 10
输出:
9

你可能感兴趣的:(算法,贪心)