对我来讲难度爆炸的一场,t2边界处理太麻烦了,做到后面属于是脑子不清楚了
6116. 计算布尔二叉树的值
给你一棵 完整二叉树 的根,这棵树有以下特征:
- 叶子节点 要么值为 0 要么值为 1 ,其中 0 表示 False ,1 表示 True 。
- 非叶子节点 要么值为 2 要么值为 3 ,其中 2 表示逻辑或 OR ,3 表示逻辑与 AND 。
计算 一个节点的值方式如下:
- 如果节点是个叶子节点,那么节点的 值 为它本身,即 True 或者 False 。
- 否则,计算 两个孩子的节点值,然后将该节点的运算符对两个孩子值进行 运算 。
返回根节点_ _root 的布尔运算值。
完整二叉树 是每个节点有 0 个或者 2 个孩子的二叉树。
叶子节点 是没有孩子的节点。
示例 1:
输入:root = [2,1,3,null,null,0,1] 输出:true 解释:上图展示了计算过程。 AND 与运算节点的值为 False AND True = False 。 OR 运算节点的值为 True OR False = True 。 根节点的值为 True ,所以我们返回 true 。
示例 2:
输入:root = [0] 输出:false 解释:根节点是叶子节点,且值为 false,所以我们返回 false 。
提示:
- 树中节点数目在 [1, 1000] 之间。
- 0 <= Node.val <= 3
- 每个节点的孩子数为 0 或 2 。
- 叶子节点的值为 0 或 1 。
- 非叶子节点的值为 2 或 3 。
思路:
后序遍历
/**
* Definition for a binary tree node.
* public class TreeNode {
* int val;
* TreeNode left;
* TreeNode right;
* TreeNode() {}
* TreeNode(int val) { this.val = val; }
* TreeNode(int val, TreeNode left, TreeNode right) {
* this.val = val;
* this.left = left;
* this.right = right;
* }
* }
*/
class Solution {
public boolean evaluateTree(TreeNode root) {
return dfs(root) == 1 ? true : false;
}
int dfs(TreeNode root) {
if (root.val == 1 || root.val == 0)
return root.val;
int l = dfs(root.left);
int r = dfs(root.right);
if (root.val == 2)
return l | r;
else return l & r;
}
}
6117. 坐上公交的最晚时间
给你一个下标从 0 开始长度为 n 的整数数组 buses ,其中 buses[i] 表示第 i 辆公交车的出发时间。同时给你一个下标从 0 开始长度为 m 的整数数组 passengers ,其中 passengers[j] 表示第 j 位乘客的到达时间。所有公交车出发的时间互不相同,所有乘客到达的时间也互不相同。
给你一个整数 capacity ,表示每辆公交车 最多 能容纳的乘客数目。
每位乘客都会搭乘下一辆有座位的公交车。如果你在 y 时刻到达,公交在 x 时刻出发,满足 y <= x 且公交没有满,那么你可以搭乘这一辆公交。最早 到达的乘客优先上车。
返回你可以搭乘公交车的最晚到达公交站时间。你 不能 跟别的乘客同时刻到达。
注意:数组 buses 和 passengers 不一定是有序的。
示例 1:
输入:buses = [10,20], passengers = [2,17,18,19], capacity = 2 输出:16 解释: 第 1 辆公交车载着第 1 位乘客。 第 2 辆公交车载着你和第 2 位乘客。 注意你不能跟其他乘客同一时间到达,所以你必须在第二位乘客之前到达。
示例 2:
输入:buses = [20,30,10], passengers = [19,13,26,4,25,11,21], capacity = 2 输出:20 解释: 第 1 辆公交车载着第 4 位乘客。 第 2 辆公交车载着第 6 位和第 2 位乘客。 第 3 辆公交车载着第 1 位乘客和你。
提示:
- n == buses.length
- m == passengers.length
- 1 <= n, m, capacity <= 105
- 2 <= buses[i], passengers[i] <= 109
- buses 中的元素 互不相同 。
- passengers 中的元素 互不相同
思路:
贪心只要能坐到最后一辆公家车上即可
时间复杂度:O(n)
class Solution {
public int latestTimeCatchTheBus(int[] b, int[] p, int c) {
Arrays.sort(b);
Arrays.sort(p);
Set<Integer> set = new HashSet<>();
for (int x : p)
set.add(x);
int s = 0, last = 0;
for (int i = 0, j = 0; i < b.length; i++) {
s = 0;
while (j < p.length && p[j] <= b[i] && s < c) {
last = p[j];
j++;
s++;
}
}
int x = b[b.length - 1];
if (s == c) x = last;
while (set.contains(x))
x--;
return x;
}
}
6118. 最小差值平方和
给你两个下标从 0 开始的整数数组 nums1 和 nums2 ,长度为 n 。
数组 nums1 和 nums2 的 差值平方和 定义为所有满足 0 <= i < n 的 (nums1[i] - nums2[i])2 之和。
同时给你两个正整数 k1 和 k2 。你可以将 nums1 中的任意元素 +1 或者 -1 至多 k1 次。类似的,你可以将 nums2 中的任意元素 +1 或者 -1 至多 k2 次。
请你返回修改数组 _nums1 至多 k1 次且修改数组 nums2 至多 k2 _次后的最小 差值平方和 。
注意:你可以将数组中的元素变成 负 整数。
示例 1:
输入:nums1 = [1,2,3,4], nums2 = [2,10,20,19], k1 = 0, k2 = 0 输出:579 解释:nums1 和 nums2 中的元素不能修改,因为 k1 = 0 和 k2 = 0 。 差值平方和为:(1 - 2)2 + (2 - 10)2 + (3 - 20)2 + (4 - 19)2 = 579 。
示例 2:
输入:nums1 = [1,4,10,12], nums2 = [5,8,6,9], k1 = 1, k2 = 1 输出:43 解释:一种得到最小差值平方和的方式为: - 将 nums1[0] 增加一次。 - 将 nums2[2] 增加一次。 最小差值平方和为: (2 - 5)2 + (4 - 8)2 + (10 - 7)2 + (12 - 9)2 = 43 。 注意,也有其他方式可以得到最小差值平方和,但没有得到比 43 更小答案的方案。
提示:
- n == nums1.length == nums2.length
- 1 <= n <= 105
- 0 <= nums1[i], nums2[i] <= 105
- 0 <= k1, k2 <= 109
思路:
二分 + 贪心
时间复杂度:O(nlogn)
class Solution {
public long minSumSquareDiff(int[] nums1, int[] nums2, int k1, int k2) {
int n = nums1.length;
int[] a = new int[n];
for (int i = 0; i < n; i++) {
a[i] = Math.abs(nums1[i] - nums2[i]);
}
long sum = 1L * k1 + k2;
int l = 0, r = 100000;
while (l < r) {
int mid = l + r >> 1;
long s = get(a, mid);
if (s <= sum)
r = mid;
else
l = mid + 1;
}
if (l == 0) return 0;
long s = get(a, l);
long minus = sum - s;
long res = 0;
for (int x : a) {
if (x < l)
res += 1L * x * x;
else {
if (minus > 0) {
res += 1L * (l - 1) * (l - 1);
minus--;
} else res += 1L * l * l;
}
}
return res;
}
long get(int[] a, int x) {
long res = 0;
for (int v : a) {
if (v > x) res += v - x;
}
return res;
}
}
6119. 元素值大于变化阈值的子数组
给你一个整数数组 nums 和一个整数 threshold 。
找到长度为 k 的 nums 子数组,满足数组中 每个 元素都 大于 threshold / k 。
请你返回满足要求的 任意 子数组的 大小 。如果没有这样的子数组,返回 -1 。
子数组 是数组中一段连续非空的元素序列。
示例 1:
输入:nums = [1,3,4,3,1], threshold = 6 输出:3 解释:子数组 [3,4,3] 大小为 3 ,每个元素都大于 6 / 3 = 2 。 注意这是唯一合法的子数组。
示例 2:
输入:nums = [6,5,6,5,8], threshold = 7 输出:1 解释:子数组 [8] 大小为 1 ,且 8 > 7 / 1 = 7 。所以返回 1 。 注意子数组 [6,5] 大小为 2 ,每个元素都大于 7 / 2 = 3.5 。 类似的,子数组 [6,5,6] ,[6,5,6,5] ,[6,5,6,5,8] 都是符合条件的子数组。 所以返回 2, 3, 4 和 5 都可以。
提示:
- 1 <= nums.length <= 105
- 1 <= nums[i], threshold <= 109
思路:
单调栈
时间复杂度:O(n)
class Solution {
public int validSubarraySize(int[] nums, int t) {
int n = nums.length;
for (int i = 0; i < n; i++) {
nums[i] = t / nums[i] + 1;
}
int[] stk = new int[n];
int p = -1;
int[] pre = new int[n], last = new int[n];
for (int i = 0; i < n; i++) {
while (p > -1 && nums[stk[p]] <= nums[i])
p--;
if (p == -1) pre[i] = -1;
else pre[i] = stk[p];
stk[++p] = i;
}
p = -1;
for (int i = n - 1; i >= 0; i--) {
while (p > -1 && nums[stk[p]] <= nums[i])
p--;
if (p == -1) last[i] = n;
else last[i] = stk[p];
stk[++p] = i;
}
for (int i = 0; i < n; i++) {
if (last[i] - pre[i] - 1 >= nums[i])
return nums[i];
}
return -1;
}
}