1. 数组变换
牛牛有一个数组,里面的数可能不相等,现在他想把数组变为:所有的数都相等。问是否可行。
牛牛可以进行的操作是:将数组中的任意一个数改为这个数的两倍。
这个操作的使用次数不限,也可以不使用,并且可以对同一个位置使用多次。
输入描述
输入一个正整数N (N <= 50)
接下来一行输入N个正整数,每个数均小于等于1e9.
输出描述
假如经过若干次操作可以使得N个数都相等,那么输出"YES", 否则输出"NO"
输入例子
2
1 2
输出例子
YES
题解
找出最大的数,判断最大的数是否是其它数的2*N倍即可。
import java.util.*;
public class Main{
public static void main(String[] args){
Scanner sc = new Scanner(System.in);
int N = sc.nextInt();
int[] a = new int[N];
int max = Integer.MIN_VALUE;
for (int i = 0; i < N; i++) {
a[i] = sc.nextInt();
if (a[i] > max) {
max = a[i];
}
}
for (int i = 0; i < N; i++) {
if (max % a[i] != 0) {
System.out.println("NO");
return;
}
}
System.out.println("YES");
}
}
2. 排序子序列
牛牛定义排序子序列为一个数组中一段连续的子序列,并且这段子序列是非递增或者非递减排序的。牛牛有一个长度为n的整数数组A,他现在有一个任务是把数组A分为若干段排序子序列,牛牛想知道他最少可以把这个数组分为几段排序子序列.
如样例所示,牛牛可以把数组A划分为[1,2,3]和[2,2,1]两个排序子序列,至少需要划分为2个排序子序列,所以输出2。
输入描述
输入的第一行为一个正整数n(1 ≤ n ≤ 10^5)
第二行包括n个整数A_i(1 ≤ A_i ≤ 10^9),表示数组A的每个数字。
输出描述
输出一个整数表示牛牛可以将A最少划分为多少段排序子序列。
输入例子
6
1 2 3 2 2 1
输出例子
2
题解
寻找波峰和波谷,关键代码(a[i] > a[i-1] && a[i] > a[i+1] || a[i] < a[i-1] && a[i] < a[i+1])
import java.util.*;
public class Main{
public static void main(String[] args){
Scanner sc = new Scanner(System.in);
int n = sc.nextInt();
int[] a = new int[n];
for (int i = 0; i < n; i++) {
a[i] = sc.nextInt();
}
int count = 1;
for (int i = 1; i < n - 1; i++) {
if (a[i] > a[i-1] && a[i] > a[i+1] || a[i] < a[i-1] && a[i] < a[i+1]) {
count++;
if(n - 3 != i) {
i++;
}
}
}
System.out.println(count);
}
}
3. 牛牛的数列
牛牛现在有一个n个数组成的数列,牛牛现在想取一个连续的子序列,并且这个子序列还必须得满足:最多只改变一个数,就可以使得这个连续的子序列是一个严格上升的子序列,牛牛想知道这个连续子序列最长的长度是多少。
输入描述
输入包括两行,第一行包括一个整数n(1 ≤ n ≤ 10^5),即数列的长度;
第二行n个整数a_i, 表示数列中的每个数(1 ≤ a_i ≤ 10^9),以空格分割。
输出描述
输出一个整数,表示最长的长度。
输入例子
6
7 2 3 1 5 6
输出例子
5
题解
对每一个数组中的数,如果前后的元素相差大于2,递增子序列数目至少为3,向前向后找递增序列并累计,第一个元素和最后一个元素另外求,得到改变每一个元素得到的最大的递增子序列的长度形成一个数组,数组中最大的值就是所求。
import java.util.*;
public class Main {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int n = sc.nextInt();
int[] a = new int[n+2];
for (int i = 1; i <= n; i++) {
a[i] = sc.nextInt();
}
int[] left = new int[n+1];
int[] right = new int[n+2];
for (int i = 1; i <= n; i++) {
left[i] = a[i-1] < a[i] ? left[i-1]+1 : 1;
}
for (int j = n; j > 0; j--) {
right[j] = a[j] < a[j+1] ? right[j+1]+1 : 1;
}
int result = 1;
for (int i = 1; i <= n; i++) {
result = Math.max(result, left[i-1] + 1);
result = Math.max(result, right[i+1] + 1);
if(a[i+1] - a[i-1] >= 2) {
result = Math.max(result, left[i-1] + right[i+1] + 1);
}
}
System.out.println(result);
}
}
4. 添加字符
牛牛手里有一个字符串A,羊羊的手里有一个字符串B,B的长度大于等于A,所以牛牛想把A串变得和B串一样长,这样羊羊就愿意和牛牛一起玩了。
而且A的长度增加到和B串一样长的时候,对应的每一位相等的越多,羊羊就越喜欢。比如"abc"和"abd"对应相等的位数为2,为前两位。
牛牛可以在A的开头或者结尾添加任意字符,使得长度和B一样。现在问牛牛对A串添加完字符之后,不相等的位数最少有多少位?
输入描述
第一行为字符串A,第二行为字符串B,A的长度小于等于B的长度,B的长度小于等于50.字符均为小写字母。
输出描述
输出一个整数表示A串添加完字符之后,不相等的位数最少有多少位?
输入例子
abe
cabc
输出例子
1
题解
字符串A与字符串B从头开始逐位比较,找到最短的不相等的位数。
import java.util.*;
public class Main {
public static void main (String[] args) {
Scanner sc = new Scanner(System.in);
String A = sc.next();
String B = sc.next();
char[] cha = A.toCharArray();
char[] chb = B.toCharArray();
int min = Integer.MAX_VALUE;
for (int i = 0; i < chb.length - cha.length + 1; i++) {
int count = 0;
for (int j = 0; j < cha.length; j++) {
if (cha[j] != chb[i+j]) {
count++;
}
}
min = Math.min(min, count);
}
System.out.println(min);
}
}
5. 变换次数
牛牛想对一个数做若干次变换,直到这个数只剩下一位数字。
变换的规则是:将这个数变成 所有位数上的数字的乘积。比如285经过一次变换后转化成285=80.
问题是,要做多少次变换,使得这个数变成个位数。
输入描述
输入一个正整数。小于等于2,000,000,000。
输出描述
输出一个整数,表示变换次数。
输入例子
285
输出例子
2
题解
将每个数拆分,重复求乘积即可。
import java.util.*;
public class Main {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int n = sc.nextInt();
int count = 0;
while (n > 10) {
n = solve(n);
count++;
}
System.out.println(count);
}
public static int solve(int n) {
int res = 1;
while (true) {
if (n < 10) {
return res *= n;
}else{
res *= (n % 10);
n = n / 10;
}
}
}
}
6. 神奇数
给出一个区间[a, b],计算区间内“神奇数”的个数。
神奇数的定义:存在不同位置的两个数位,组成一个两位数(且不含前导0),且这个两位数为质数。
比如:153,可以使用数字3和数字1组成13,13是质数,满足神奇数。同样153可以找到31和53也为质数,只要找到一个质数即满足神奇数。
输入描述
输入为两个整数a和b,代表[a, b]区间 (1 ≤ a ≤ b ≤ 10000)。
输出描述
输出为一个整数,表示区间内满足条件的整数个数
输入例子
11 20
输出例子
6
题解
首先保存[10,99]中的所有质数,然后开双重循环,外层循环遍历[a,b],内层循环遍历保存的质数,都转换为字符串,使用String.indexOf( )判断外层循环每一个数是否包含某个质数的所有位数。
import java.util.*;
public class Main {
public static void main (String[] args) {
Scanner sc = new Scanner(System.in);
int a = sc.nextInt();
int b = sc.nextInt();
// 存储质数
List<Integer> list = new ArrayList<>();
for (int i = 10; i <= 99; i++) {
boolean isOdd = true;
for (int j = 2; j <= Math.sqrt(i); j++) {
if(i % j == 0) {
isOdd = false;
break;
}
}
if (isOdd) {
list.add(i);
}
}
int cnt = 0;
for (int i = a; i <= b; i++) {
String str = String.valueOf(i);
for (Integer num : list) {
String ge = String.valueOf(num%10);
String shi = String.valueOf(num/10);
// i = 277这种情况
if (ge.equals(shi)) {
int index = str.indexOf(ge);
if(index != -1 && str.indexOf(shi, index + 1) != -1){
cnt++;
break;
}
}else {
if(str.indexOf(ge) != -1 && str.indexOf(shi) != -1) {
cnt++;
break;
}
}
}
}
System.out.println(cnt);
}
}
7. 组队竞赛
牛牛举办了一次编程比赛,参加比赛的有3*n个选手,每个选手都有一个水平值a_i.现在要将这些选手进行组队,一共组成n个队伍,即每个队伍3人.牛牛发现队伍的水平值等于该队伍队员中第二高水平值。
例如:
一个队伍三个队员的水平值分别是3,3,3.那么队伍的水平值是3
一个队伍三个队员的水平值分别是3,2,3.那么队伍的水平值是3
一个队伍三个队员的水平值分别是1,5,2.那么队伍的水平值是2
为了让比赛更有看点,牛牛想安排队伍使所有队伍的水平值总和最大。
如样例所示:
如果牛牛把6个队员划分到两个队伍
如果方案为:
team1:{1,2,5}, team2:{5,5,8}, 这时候水平值总和为7.
而如果方案为:
team1:{2,5,8}, team2:{1,5,5}, 这时候水平值总和为10.
没有比总和为10更大的方案,所以输出10.
输入描述
输入的第一行为一个正整数n(1 ≤ n ≤ 10^5)
第二行包括3*n个整数a_i(1 ≤ a_i ≤ 10^9),表示每个参赛选手的水平值.
输出描述
输出一个整数表示所有队伍的水平值总和最大值.
输入例子
2
5 2 8 5 1 5
输出例子
10
题解
对数组排序,每只队伍的值包含{小,中,大}三个数,要使每支队伍的值尽可能大,则使“小”的值最小,“大”的值最大,“中”的值尽可能大,故排序后“小”值从左往右取,“中”值和“大”值从右往左取即可。
import java.util.*;
public class Main {
public static void main (String[] args) {
Scanner sc = new Scanner(System.in);
int n = sc.nextInt();
long[] a = new long[n*3];
for (int i = 0; i < n*3; i++) {
a[i] = sc.nextLong();
}
Arrays.sort(a);
long sum = 0;
for (int j = a.length - 2, i = n; i > 0; i--, j -= 2) {
sum += a[j];
}
System.out.println(sum);
}
}