LeetCode周赛360
A题
略
B题
题意
要求构造一个数组arr,长度为n,里面任意两个元素相加之和不等于target。求这样一个数组的和的最小值。
和双周赛359的B题类似,先从1构造到target >> 1,然后再从target开始继续构造。
代码
class Solution {
public long minimumPossibleSum(int n, int target) {
int p = target / 2 + 1;
long sum = 0;
int start = 1;
while(--n >= 0) {
sum += start++;
if (start == p) {
start = target;
}
}
return sum;
}
}
C题
题意
给出一个数组arr,里面的每个元素的值保证为2的幂数,每个元素a又可以被拆分成两个x,x + x = a。要求求出最少执行多少次拆分之后数组里面的某一个子序列的和为target。
思路
我们可以先将target视为一个二进制数,那么题目要求的就是target中每一个1都需要在原数组中出现,那么我们对每一个1,从小到大开始求是否会在原数组中出现。我们知道一个理论,如果原数组中,小于等于当前位上的2进制数之和大于等于当前1所代表的数的值,那么一定能组合成当前1;那么对于每一个1,我们先判断小于当前1的数之和是否大于等于当前1代表的val,如果是的,直接选取即可,如果不是,再找当前位置1的数组有没有在原数组中出现,如果有则取它,否则就需要对更前面的1进行拆分。
代码
class Solution {
public int minOperations(List<Integer> nums, int target) {
var sb = new StringBuilder();
while(target != 0) {
if ((target & 1) == 1) {
sb.append(1);
} else {
sb.append(0);
}
target >>= 1;
}
char[] chars = sb.toString().toCharArray();
var map = new HashMap<Integer, Integer>();
int ans = 0;
for (var num : nums) {
int bit = 0;
while (num != 1) {
num >>= 1;
bit++;
}
map.merge(bit, 1, Integer::sum);
ans = Math.max(ans, bit);
}
var cnt = new int[Math.max(ans, chars.length) + 5];
for (int i = 0; i <= ans; i++) {
cnt[i] = map.getOrDefault(i, 0);
}
ans = 0;
int pre = 0, bit = 1;
for (int i = 0; i < chars.length; i++) {
if (chars[i] == '1') {
if (pre >= bit) {
pre -= bit;
} else {
int p = find(i, cnt);
if (p == -1) {
return -1;
}
ans += p;
}
}
pre += cnt[i] * bit;
bit <<= 1;
}
return ans;
}
private int find(int id, int[] cnt) {
int ans = -1;
for (int i = id; i < cnt.length; i++) {
if (cnt[i] > 0) {
cnt[i]--;
for (int j = id; j < i; j++) {
cnt[j]++;
}
ans = i - id;
break;
}
}
return ans;
}
}
D题
题意
选择一个id,id传k次之后的值最大。
思路
树上倍增板子题。
代码
class Solution {
public long getMaxFunctionValue(List<Integer> receiver, long k) {
var fa = new int[receiver.size()][log2(k) + 1];
var sum = new long[receiver.size()][log2(k) + 1];
for (int i = 0; i < receiver.size(); i++) {
fa[i][0] = receiver.get(i);
sum[i][0] = fa[i][0];
}
for (int j = 1; j < fa[0].length; j++) {
for (int i = 0; i < fa.length; i++) {
int pa = fa[i][j - 1];
fa[i][j] = fa[pa][j - 1];
sum[i][j] = sum[i][j - 1] + sum[pa][j - 1];
}
}
long max = 0;
for (int i = 0; i < receiver.size(); i++) {
long k1 = k;
long ans = i;
int node = i;
while(k1 != 0) {
var len = Long.numberOfTrailingZeros(k1);
ans += sum[node][len];
node = fa[node][len];
k1 &= (k1 - 1);
}
max = Math.max(max, ans);
}
return max;
}
public int log2(long n) {
return (int) (Math.log10(n) / Math.log10(2));
}
}