LeetCode第12场双周赛

1、力扣排行榜
新一轮的「力扣杯」编程大赛即将启动,为了动态显示参赛者的得分数据,需要设计一个排行榜 Leaderboard。
请你帮忙来设计这个 Leaderboard 类,使得它有如下 3 个函数:
addScore(playerId, score):
假如参赛者已经在排行榜上,就给他的当前得分增加 score 点分值并更新排行。
假如该参赛者不在排行榜上,就把他添加到榜单上,并且将分数设置为 score。
top(K):返回前 K 名参赛者的 得分总和。
reset(playerId):将指定参赛者的成绩清零。题目保证在调用此函数前,该参赛者已有成绩,并且在榜单上。

请注意,在初始状态下,排行榜是空的。

示例 1:
输入:
[“Leaderboard”,“addScore”,“addScore”,“addScore”,“addScore”,“addScore”,“top”,“reset”,“reset”,“addScore”,“top”]
[[],[1,73],[2,56],[3,39],[4,51],[5,4],[1],[1],[2],[2,51],[3]]
输出:
[null,null,null,null,null,null,73,null,null,null,141]

解释:
Leaderboard leaderboard = new Leaderboard ();
leaderboard.addScore(1,73); // leaderboard = [[1,73]];
leaderboard.addScore(2,56); // leaderboard = [[1,73],[2,56]];
leaderboard.addScore(3,39); // leaderboard = [[1,73],[2,56],[3,39]];
leaderboard.addScore(4,51); // leaderboard = [[1,73],[2,56],[3,39],[4,51]];
leaderboard.addScore(5,4); // leaderboard = [[1,73],[2,56],[3,39],[4,51],[5,4]];
leaderboard.top(1); // returns 73;
leaderboard.reset(1); // leaderboard = [[2,56],[3,39],[4,51],[5,4]];
leaderboard.reset(2); // leaderboard = [[3,39],[4,51],[5,4]];
leaderboard.addScore(2,51); // leaderboard = [[2,51],[3,39],[4,51],[5,4]];
leaderboard.top(3); // returns 141 = 51 + 51 + 39;

提示:

1 <= playerId, K <= 10000
题目保证 K 小于或等于当前参赛者的数量
1 <= score <= 100
最多进行 1000 次函数调用
class Leaderboard {

	Map<Integer, Integer> scores = new HashMap<Integer, Integer>();
	LinkedList<Integer> list = new LinkedList<Integer>();

	public Leaderboard() {

	}

	public void addScore(int playerId, int score) {
		Integer v = scores.get(playerId);
		if (v == null) {
			scores.put(playerId, score);
			addList(score);
		} else {
			scores.put(playerId, score + v);
			removeList(v);
			addList(score + v);
		}
	}

	public int top(int K) {
		int ans = 0;
		for (Integer in : list) {
			K--;
			ans += in;
			if (K == 0) {
				return ans;
			}
		}
		return ans;
	}

	public void reset(int playerId) {
		Integer v = scores.get(playerId);
		scores.remove(new Integer(playerId));
		removeList(v);
	}

	private void removeList(Integer v) {
		list.remove(v);
	}

	private void addList(int score) {
		int v = list.size();
		for (int i = 0; i < list.size(); i++) {
			if (score > list.get(i)) {
				v = i;
				break;
			}
		}
		list.add(v, score);
	}
}

2、数组变换
首先,给你一个初始数组 arr。然后,每天你都要根据前一天的数组生成一个新的数组。
第 i 天所生成的数组,是由你对第 i-1 天的数组进行如下操作所得的:
假如一个元素小于它的左右邻居,那么该元素自增 1。
假如一个元素大于它的左右邻居,那么该元素自减 1。
首、尾元素 永不 改变。
过些时日,你会发现数组将会不再发生变化,请返回最终所得到的数组。

示例 1:
输入:[6,2,3,4]
输出:[6,3,3,4]
解释:
第一天,数组从 [6,2,3,4] 变为 [6,3,3,4]。
无法再对该数组进行更多操作。

示例 2:
输入:[1,6,3,4,3,5]
输出:[1,4,4,4,4,5]
解释:
第一天,数组从 [1,6,3,4,3,5] 变为 [1,5,4,3,4,5]。
第二天,数组从 [1,5,4,3,4,5] 变为 [1,4,4,4,4,5]。
无法再对该数组进行更多操作。

提示:
1 <= arr.length <= 100
1 <= arr[i] <= 100

class Solution {
    public List<Integer> transformArray(int[] arr) {
		boolean change = true;
		while (change) {
			change = false;
			int[] newArr = Arrays.copyOf(arr, arr.length);
			for (int i = 1; i < arr.length - 1; i++) {
				if (newArr[i] < arr[i - 1] && newArr[i] < arr[i + 1]) {
					newArr[i]++;
					change = true;
					continue;
				}
				if (newArr[i] > arr[i - 1] && newArr[i] > arr[i + 1]) {
					newArr[i]--;
					change = true;
				}
			}
			arr = newArr;
		}
		List<Integer> ans = new ArrayList<Integer>();
		for (int i = 0; i < arr.length; i++) {
			ans.add(arr[i]);
		}
		return ans;
	}
}

3、树的直径

给你这棵「无向树」,请你测算并返回它的「直径」:这棵树上最长简单路径的 边数。
我们用一个由所有「边」组成的数组 edges 来表示一棵无向树,其中 edges[i] = [u, v] 表示节点 u 和 v 之间的双向边。
树上的节点都已经用 {0, 1, …, edges.length} 中的数做了标记,每个节点上的标记都是独一无二的。

示例 1:
输入:edges = [[0,1],[0,2]]
输出:2
解释:
这棵树上最长的路径是 1 - 0 - 2,边数为 2。

示例 2:
输入:edges = [[0,1],[1,2],[2,3],[1,4],[4,5]]
输出:4
解释:
这棵树上最长的路径是 3 - 2 - 1 - 4 - 5,边数为 4。

提示:
0 <= edges.length < 10^4
edges[i][0] != edges[i][1]
0 <= edges[i][j] <= edges.length
edges 会形成一棵无向树

class Solution {
    public int treeDiameter(int[][] edges) {
		if (edges.length == 0) {
			return 0;
		}
		Map<Integer, Node> map = new HashMap<Integer, Node>();
		Node root = new Node();
		root.len = 0;
		Node left = new Node();
		left.len = 1;
		root.children.add(left);
		Set<Integer> set = new HashSet<Integer>();
		set.add(0);
		map.put(edges[0][0], root);
		map.put(edges[0][1], left);
		while (set.size() < edges.length) {
			for (int i = 1; i < edges.length; i++) {
				if (set.contains(i)) {
					continue;
				}
				int key1 = edges[i][0];
				int key2 = edges[i][1];
				if (map.containsKey(key1)) {
					Node no = map.get(key1);
					Node nNo = new Node();
					nNo.len = no.len + 1;
					map.put(key2, nNo);
					set.add(i);
					no.children.add(nNo);
				} else if (map.containsKey(key2)) {
					Node no = map.get(key2);
					Node nNo = new Node();
					map.put(key1, nNo);
					set.add(i);
					nNo.len = no.len + 1;
					no.children.add(nNo);
				}
			}
		}
		getAns(root);
		return ans;
	}

	private void getAns(Node root) {
		if (root.children.isEmpty()) {
			ans = Math.max(ans, 0);
			return;
		}
		int a1 = root.len;
		int a2 = root.len;
		for (Node child : root.children) {
			getAns(child);
			if (child.len > a1) {
				a1 = child.len;
				if (a1 > a2) {
					int v = a1;
					a1 = a2;
					a2 = v;
				}
			}
		}
		ans = Math.max(a1 - root.len + a2 - root.len, ans);
		root.len = Math.max(a1, a2);
	}

	int ans = 0;

	class Node {
		int val;
		List<Node> children = new ArrayList<Node>();
		int len;
	}
}

4、删除回文子数组
给你一个整数数组 arr,每一次操作你都可以选择并删除它的一个 回文 子数组 arr[i], arr[i+1], …, arr[j]( i <= j)。
注意,每当你删除掉一个子数组,右侧元素都会自行向前移动填补空位。
请你计算并返回从数组中删除所有数字所需的最少操作次数。

示例 1:
输入:arr = [1,2]
输出:2

示例 2:
输入:arr = [1,3,4,1,5]
输出:3
解释:先删除 [4],然后删除 [1,3,1],最后再删除 [5]。

提示:
1 <= arr.length <= 100
1 <= arr[i] <= 20

class Solution {
    public int minimumMoves(int[] arr) {
		int[][] ans = new int[arr.length][arr.length];
		ans[0][0] = 1;
		for (int i = 1; i < arr.length; i++) {
			ans[i][i] = 1;
			for (int j = i - 1; j >= 0; j--) {
				int re = Integer.MAX_VALUE;
				for (int k = j; k < i; k++) {
					if (arr[k] == arr[i]) {
						re = Math.min(re, (k - 1 >= 0 ? ans[j][k - 1] : 0)
								+ (k + 1 > i - 1 ? 1 : ans[k + 1][i - 1]));
					} else {
						re = Math.min(re, (k - 1 >= 0 ? ans[j][k - 1] : 0) + 1
								+ ans[k][i - 1]);
					}
				}

				ans[j][i] = re;
			}
		}
		return ans[0][arr.length - 1];
	}
}
发布了127 篇原创文章 · 获赞 16 · 访问量 1万+

猜你喜欢

转载自blog.csdn.net/qq_33321609/article/details/102882339