美团2022.03.05(前两道),欢迎指正。
美团
题目一:
小团最近在玩手机上的四川麻将。四川麻将的一种玩法是玩家摸完牌之后选择三张花色一样的牌按某种顺序换给其他人。为了尽可能破坏对手的游戏体验,小团每次都会选择不连续的三张牌换出去。比如小团手上有14568这5张条子,则他可能会选择158这三张条子换出去。爱思考的小团马上对这个问题进行了推广。
小团把这个问题进行了简化,现在他给了你一个可重集合,并希望你从中选出一个尽可能大的子集使得其中没有两个数是“连续”的(连续是指即这两个数之差的绝对值不超过1)。
最大不连续子数组个数。
public static void main(String []args) {
Scanner in = new Scanner(System.in);
int n = in.nextInt();
int num[] = new int[n];
for (int i = 0; i < n; i++) {
num[i] = in.nextInt();
}
Arrays.sort(num);
int j = 0;
int max = -1;
int dp[] = new int[n];
dp[0] = 1;
int ori = num[j];
for (int i = j + 1; i < n; i++) {
if (num[i] - num[i - 1] > 1 || num[i] - ori > 1) {
dp[i] = dp[i - 1] + 1;
ori = num[i];
} else {
dp[i] = dp[i - 1];
}
}
max = Math.max(dp[n - 1], max);
System.out.println(max);
}
题目二:
最大子段和是一个经典问题,即对于一个数组找出其和最大的子数组。
现在允许你在求解该问题之前翻转这个数组的连续一段(如翻转{1,2,3,4.5,6]的第三个到第五个元素组成的子数组得到的是{1,2.5,4,3,6}),则翻转后该数组的最大子段和最大能达到多少?
输入描述
第一行有一个正整数n(1<=n< =100000),代表数组长度。
第二行有n个空格隔开的整数(-1000<=ai<=1000),代表给出数组。
输出描述
输出一个整数,代表若允许你翻转一个子数组,则翻转后所得数组的最大子段和最大能到多少。
public static void main(String []args) {
Scanner in = new Scanner(System.in);
int n = in.nextInt();
int num[] = new int[n];
for (int i = 0; i < n; i++) {
num[i] = in.nextInt();
}
int max = Integer.MIN_VALUE;
for (int i = 0; i < n - 1; i++) {
for (int j = i + 1; j < n; j++) {
int temp[] = new int[n];
int m = 0;
for (int k = 0; k < i; k++) {
temp[m] = num[k];
m++;
}
for (int k = j; k >= i ; k--) {
temp[m] = num[k];
m++;
}
for (int k = j + 1; k < n; k++) {
temp[m] = num[k];
m++;
}
max = Math.max(max, maxSubArray(temp));
}
}
System.out.println(max);
}
public static int maxSubArray(int[] nums) {
int dp = nums[0];
int max = nums[0];
for (int i = 1; i < nums.length; i++) {
if (dp < 0) {
dp = nums[i];
} else {
dp = dp + nums[i];
}
max = Math.max(max, dp);
}
return max;
}