20200531
给你一个整数数组 nums,请你选择数组的两个不同下标 i 和 j,使(nums[i]-1)*(nums[j]-1)
取得最大值。
请你计算并返回该式的最大值。
示例 1:
输入:nums = [3,4,5,2]
输出:12
解释:如果选择下标 i=1 和 j=2(下标从 0 开始),则可以获得最大值,(nums[1]-1)*(nums[2]-1) = (4-1)*(5-1) = 3*4 = 12 。
示例 2:
输入:nums = [1,5,4,5]
输出:16
解释:选择下标 i=1 和 j=3(下标从 0 开始),则可以获得最大值 (5-1)*(5-1) = 16 。
示例 3:
输入:nums = [3,7]
输出:12
提示:
- 2 <= nums.length <= 500
- 1 <= nums[i] <= 10^3
冒泡模式,不过排序两个就可以了。
class Solution {
public int maxProduct(int[] nums) {
int res = 0;
int temp = 0;
int len = nums.length;
for(int i = 0; i < 2; i++){
for(int j = 0; j < nums.length - i - 1; j++){
if(nums[j] >= nums[j + 1]){
temp = nums[j];
nums[j] = nums[j + 1];
nums[j + 1] = temp;
}
}
}
return (nums[len - 1] - 1) * (nums[len - 2] - 1);
}
}
矩形蛋糕的高度为 h 且宽度为 w,给你两个整数数组 horizontalCuts 和 verticalCuts,其中 horizontalCuts[i] 是从矩形蛋糕顶部到第 i 个水平切口的距离,类似地, verticalCuts[j] 是从矩形蛋糕的左侧到第 j 个竖直切口的距离。
请你按数组 horizontalCuts 和 verticalCuts 中提供的水平和竖直位置切割后,请你找出 面积最大 的那份蛋糕,并返回其 面积 。由于答案可能是一个很大的数字,因此需要将结果对 10^9 + 7 取余后返回。
示例 1:
输入:h = 5, w = 4, horizontalCuts = [1,2,4], verticalCuts = [1,3]
输出:4
解释:上图所示的矩阵蛋糕中,红色线表示水平和竖直方向上的切口。切割蛋糕后,绿色的那份蛋糕面积最大。
示例 2:
输入:h = 5, w = 4, horizontalCuts = [3,1], verticalCuts = [1]
输出:6
解释:上图所示的矩阵蛋糕中,红色线表示水平和竖直方向上的切口。切割蛋糕后,绿色和黄色的两份蛋糕面积最大。
示例 3:
输入:h = 5, w = 4, horizontalCuts = [3], verticalCuts = [3]
输出:9
提示:
- 2 <= h, w <= 10^9
- 1 <= horizontalCuts.length < min(h, 10^5)
- 1 <= verticalCuts.length < min(w, 10^5)
- 1 <= horizontalCuts[i] < h
- 1 <= verticalCuts[i] < w
- 题目数据保证 horizontalCuts 中的所有元素各不相同
- 题目数据保证 verticalCuts 中的所有元素各不相同
分别找到row和col的最大距离,两块距离相乘就可以了。
tips:结果全部用long来表示,最后对1000000007取余,然后转int输出。
class Solution {
public int maxArea(int h, int w, int[] horizontalCuts, int[] verticalCuts) {
int hmax = 0, wmax = 0;
Arrays.sort(horizontalCuts);
Arrays.sort(verticalCuts);
for(int i = 0; i < horizontalCuts.length - 1; i++){
hmax = Math.max(hmax, horizontalCuts[i + 1] - horizontalCuts[i]);
}
hmax = Math.max(hmax, horizontalCuts[0] - 0);
hmax = Math.max(hmax, h - horizontalCuts[horizontalCuts.length - 1]);
for(int i = 0; i < verticalCuts.length - 1; i++){
wmax = Math.max(wmax, verticalCuts[i + 1] - verticalCuts[i]);
}
wmax = Math.max(wmax, verticalCuts[0] - 0);
wmax = Math.max(wmax, w - verticalCuts[verticalCuts.length - 1]);
long ans = (long)hmax * (long)wmax;
long a = 1000000007;
return (int)(ans%a);
}
}
n 座城市,从 0 到 n-1 编号,其间共有 n-1 条路线。因此,要想在两座不同城市之间旅行只有唯一一条路线可供选择(路线网形成一颗树)。去年,交通运输部决定重新规划路线,以改变交通拥堵的状况。
路线用 connections 表示,其中 connections[i] = [a, b] 表示从城市 a 到 b 的一条有向路线。
今年,城市 0 将会举办一场大型比赛,很多游客都想前往城市 0 。
请你帮助重新规划路线方向,使每个城市都可以访问城市 0 。返回需要变更方向的最小路线数。
题目数据 保证 每个城市在重新规划路线方向后都能到达城市 0 。
示例 1:
输入:n = 6, connections = [[0,1],[1,3],[2,3],[4,0],[4,5]]
输出:3
解释:更改以红色显示的路线的方向,使每个城市都可以到达城市 0 。
示例 2:
输入:n = 5, connections = [[1,0],[1,2],[3,2],[3,4]]
输出:2
解释:更改以红色显示的路线的方向,使每个城市都可以到达城市 0 。
示例 3:
输入:n = 3, connections = [[1,0],[2,0]]
输出:0
提示:
- 2 <= n <= 5 * 10^4
- connections.length == n-1
- connections[i].length == 2
- 0 <= connections[i][0], connections[i][1] <= n-1
- connections[i][0] != connections[i][1]
BFS + 邻接表
class Solution {
public int minReorder(int n, int[][] connections) {
int result = 0;
Map<Integer, Set<Integer>> conn_idx = new HashMap<>();//表示含有城市i的connection的index
boolean[] visited = new boolean[n];//某条边是否被访问过
for(int i = 0; i < connections.length; i++){
int city1 = connections[i][0];
int city2 = connections[i][1];
if(!conn_idx.containsKey(city1)){
conn_idx.put(city1, new HashSet<>());
}
conn_idx.get(city1).add(i);
if(!conn_idx.containsKey(city2)){
conn_idx.put(city2, new HashSet<>());
}
conn_idx.get(city2).add(i);
}
// bfs
Queue<Integer> queue = new LinkedList<>();
queue.offer(0);
while(!queue.isEmpty()){
int curr = queue.poll();
// 对和curr相关的连接进行遍历,通过上面储存的连接的index
for(int i : conn_idx.get(curr)){
if(visited[i]){
continue;
}
visited[i] = true;
int a = connections[i][0];//连接的起始
int b = connections[i][1];//连接的终点
// 如果当前点是出的,那么要修改为入,result++
result += ((a == curr) ? 1 : 0);
a = ((a == curr) ? b : a);
queue.offer(a);
}
}
return result;
}
}
以下解法要求connections按照顺序给出(刚好这道题的测试用例都是按顺序的)
class Solution {
public int minReorder(int n, int[][] connections) {
Set<Integer> available = new HashSet<>();
available.add(0);
int change = 0;
for(int[] line : connections){
if(available.contains(line[1])){
available.add(line[0]);
}else{
change++;
available.add(line[1]);
}
}
return change;
}
}
桌面上有 2n 个颜色不完全相同的球,球上的颜色共有 k 种。给你一个大小为 k 的整数数组 balls ,其中 balls[i] 是颜色为 i 的球的数量。
所有的球都已经 随机打乱顺序 ,前 n 个球放入第一个盒子,后 n 个球放入另一个盒子(请认真阅读示例 2 的解释部分)。
注意:这两个盒子是不同的。例如,两个球颜色分别为 a 和 b,盒子分别为 [] 和 (),那么 [a] (b) 和 [b] (a) 这两种分配方式是不同的(请认真阅读示例 1 的解释部分)。
请计算「两个盒子中球的颜色数相同」的情况的概率。
示例 1:
输入:balls = [1,1]
输出:1.00000
解释:球平均分配的方式只有两种:
- 颜色为 1 的球放入第一个盒子,颜色为 2 的球放入第二个盒子
- 颜色为 2 的球放入第一个盒子,颜色为 1 的球放入第二个盒子
这两种分配,两个盒子中球的颜色数都相同。所以概率为 2/2 = 1 。
示例 2:
输入:balls = [2,1,1]
输出:0.66667
解释:球的列表为 [1, 1, 2, 3]
随机打乱,得到 12 种等概率的不同打乱方案,每种方案概率为 1/12 :
[1,1 / 2,3], [1,1 / 3,2], [1,2 / 1,3], [1,2 / 3,1], [1,3 / 1,2], [1,3 / 2,1], [2,1 / 1,3], [2,1 / 3,1], [2,3 / 1,1], [3,1 / 1,2], [3,1 / 2,1], [3,2 / 1,1]
然后,我们将前两个球放入第一个盒子,后两个球放入第二个盒子。
这 12 种可能的随机打乱方式中的 8 种满足「两个盒子中球的颜色数相同」。
概率 = 8/12 = 0.66667
示例 3:
输入:balls = [1,2,1,2]
输出:0.60000
解释:球的列表为 [1, 2, 2, 3, 4, 4]。要想显示所有 180 种随机打乱方案是很难的,但只检查「两个盒子中球的颜色数相同」的 108 种情况是比较容易的。
概率 = 108 / 180 = 0.6 。
示例 4:
输入:balls = [3,2,1]
输出:0.30000
解释:球的列表为 [1, 1, 1, 2, 2, 3]。要想显示所有 60 种随机打乱方案是很难的,但只检查「两个盒子中球的颜色数相同」的 18 种情况是比较容易的。
概率 = 18 / 60 = 0.3 。
示例 5:
输入:balls = [6,6,6,6,6,6]
输出:0.90327
提示:
- 1 <= balls.length <= 8
- 1 <= balls[i] <= 6
- sum(balls) 是偶数
- 答案与真实值误差在 10^-5 以内,则被视为正确答案
参考B站y神的讲解,原网址https://www.bilibili.com/video/BV1PA411q7c5
class Solution:
def fact(self, n):
res = 1
for i in range(1, n + 1): res *= i
return res
def get_tot(self, balls):
tot = self.fact(sum(balls))
for b in balls:
if b:
tot /= self.fact(b)
return tot
def dfs(self, u, balls, left, right, ts, ls, rs):
if ls * 2 > ts or rs * 2 > ts: return 0
if u == len(balls):
l = 0
r = 0
for i in range(len(balls)):
if left[i]: l += 1
if right[i]: r += 1
if l != r: return 0
return self.get_tot(left) * self.get_tot(right)
res = 0
for i in range(balls[u] + 1):
left[u] = i
right[u] = balls[u] - i
res += self.dfs(u + 1, balls, left, right, ts, ls + left[u], rs + right[u])
return res
def getProbability(self, balls: List[int]) -> float:
tot = self.get_tot(balls)
left = [0 for i in range(len(balls))]
right = [0 for i in range(len(balls))]
return self.dfs(0, balls, left, right, sum(balls), 0, 0) / tot
- 我的公众号: 每日分享LeetCode, 让你走在路上坐在车上也能看算法题,欢迎大家扫码关注。