思路:按照题意模拟即可。
class Solution {
public List<Integer> mostVisited(int n, int[] rounds) {
int mx = 0;
int[] nums = new int[n + 1];
List<Integer> ans = new ArrayList<>();
nums[rounds[0]]++;
mx = nums[rounds[0]];
for (int i = 1; i < rounds.length; i++) {
for (int j = rounds[i - 1] + 1; j <= rounds[i]; j++) {
nums[j]++;
mx = Math.max(mx, nums[j]);
}
if (rounds[i] < rounds[i - 1]) {
for (int j = rounds[i - 1] + 1; j <= n; j++) {
nums[j]++;
mx = Math.max(mx, nums[j]);
}
for (int j = 1; j <= rounds[i]; j++) {
nums[j]++;
mx = Math.max(mx, nums[j]);
}
}
}
for (int i = 1; i <= n; i++) {
if (mx == nums[i])
ans.add(i);
}
return ans;
}
}
思路:对数组进行排序,在每一轮中,去掉一个最大值和最小值,然后你拿走当前最大的,可以证明结果最优。
class Solution {
public int maxCoins(int[] piles) {
int ans = 0;
Arrays.sort(piles);
int len = piles.length;
int l = 0, r = len - 1;
while (l <= r) {
ans += piles[r - 1];
r -= 2;
l++;
}
return ans;
}
}
思路:经典区间合并问题,对于这类题目套路是不变的,我们定义l数组和r数组,分别存储当前每一个索引位置的最左端和最右端能延伸到的位置,之后多开一个数组记录每一个区间的长度(也就是连续1的数量)即可。最后判断m长度的区间最后一次出现在什么时候就ok。
class Solution {
public int findLatestStep(int[] arr, int m) {
int n = arr.length, ans = 0;
int[] l = new int[n + 2];
int[] r = new int[n + 2];
int[] sum = new int[n + 2];
int[] nums = new int[n + 1];
l[n + 1] = r[n + 1] = n + 1;
for (int i = 1; i <= n; i++)
l[i] = r[i] = i;
Arrays.fill(sum, -1);
for (int i = 1; i <= n; i++) {
int now = 1;
int index = arr[i - 1];
int sum_l = sum[l[index - 1]];
int sum_r = sum[r[index + 1]];
if (sum_l != -1) {
l[index] = l[index - 1];
now += sum_l;
nums[sum[l[index]]]--;
}
if (sum_r != -1) {
r[index] = r[index + 1];
now += sum_r;
nums[sum[r[index]]]--;
}
int ll = l[index], rr = r[index];
r[l[index]] = rr;
l[r[index]] = ll;
sum[l[index]] = sum[r[index]] = now;
nums[now]++;
if (nums[m] != 0)
ans = i;
}
return ans == 0 ? -1 : ans;
}
}
思路:定义dp[l][r]表示在区间[l,r]内Alice能获得的最大分数,最后按照分治的思路动态规划即可。
class Solution {
int[] sum;
int[][] dp;
public int stoneGameV(int[] stoneValue) {
int n = stoneValue.length;
sum = new int[n + 1];
dp = new int[n + 1][n + 1];
for (int i = 1; i <= n; i++)
sum[i] = sum[i - 1] + stoneValue[i - 1];
for (int i = 0; i <= n; i++)
Arrays.fill(dp[i], -1);
return f(sum, 1, n);
}
private int f(int[] sum, int l, int r) {
if (dp[l][r] != -1)
return dp[l][r];
if (l == r) return 0;
int res = 0;
for (int k = l; k < r; k++) {
int tmp = 0;
if (sum[r] - sum[k] > sum[k] - sum[l - 1])
tmp = sum[k] - sum[l - 1] + f(sum, l, k);
else if (sum[r] - sum[k] < sum[k] - sum[l - 1])
tmp = sum[r] - sum[k] + f(sum, k + 1, r);
else
tmp = Math.max(sum[k] - sum[l - 1] + f(sum, l, k), sum[r] - sum[k] + f(sum, k + 1, r));
res = Math.max(res, tmp);
}
return dp[l][r] = res;
}
}