(声明:我没有全量用例,所以不保证全过,只能说给出样例输入可以跑过。不要指望我这是标准答案,这也是自己写的。要标准答案的自己写去。)
目录
第七题 身高排序(绝对差值)【考察 list.sort(new Comparator<>(){})】
第一题 勾股元组数
// 如果三个正整数A B C ,A²+B²=C²则为勾股数
// 如果ABC之间两两互质,即A与B A与C B与C均互质没有公约数,
// 则称其为勾股数元组。
// 请求出给定n m 范围内所有的勾股数元组
// 输入描述
// 起始范围 1<n<10000 n<m<10000
// 输出目描述
// abc 保证a<b<c输出格式 a b c
// 多组勾股数元组 按照a升序b升序 c升序的排序方式输出。
// 给定范围内,找不到勾股数元组时,输出 Na// 案例
// 输入
// 1
// 20
// 输出
// 3 4 5
// 5 12 13
// 8 15 17// 输入
// 5
// 10
// 输出
// Na【笔记】
关键点
1. a b 互质,即 a 和 b 的公约数==1
这里用阿基里德算法(辗转相除法),递归方式,如果最后结果==1,表示a,b 互质
gcd(a,b) = gcd(b, a%b)
2. i,j,k 用穷举法得出,满足条件 i<j<k,且 i,j,k 两两互质
import java.util.Scanner;
public class Test1 {
public static void main(String[] args){
Scanner sc = new Scanner(System.in);
int count = 0;
int n = sc.nextInt();
int m = sc.nextInt();
for(int i = n; i<m; i++){
for(int j=n+1; j<m; j++){
for(int k=j+1; k<=m; k++){
if(i<j && j<k && (i*i + j*j == k*k) &&gcd(i,j)==1 && gcd(j,k)==1 && gcd(i,k)==1){
System.out.println(i+","+j+","+k);
count++;
}
}
}
}
if(0 == count)
System.out.println("Na");
}
public static int gcd(int a, int b){
if(0==b) return a;
return gcd(b,a%b);
}
}
第二题 整数对最小和
// 给定两个整数数组
//array1 array2 数组元素按升序排列
// 假设从arr1 arr2中分别取出一个元素,可构成一对元素
// 现在需要取出k对元素,并对取出的所有元素求和
// 计算和的最小值
// 注意:两对元素对应arr1 arr2的下标是相同的
// 视为同一对元素//输入描述
// 输入两行数组arr1 arr2
// 每行首个数字为数组大小size 0<size<=100
// arr1,2中的每个元素 0< <1000
// 接下来一行 正整数k 0<k<=arr1.size * arr2.size
// 输出描述
// 满足要求的最小值// 例子
//输入
// 3 1 1 2
// 3 1 2 3
// 2//输出
// 4//说明:用例中需要取两个元素,
// 取第一个数组第0个元素与第二个数组第0个元素组成一个元素
// [1,1]
//取第一个数组第1个元素与第二个数组第0个元素组成一个元素
// [1,1]//求和为1+1+1+1=4 ,满足要求最小
import java.util.*;
public class Test2 {
public static void main(String[] args){
Scanner sc = new Scanner(System.in);
String[] str1 = sc.nextLine().split("\\s+");
String[] str2 = sc.nextLine().split("\\s+");
int n = sc.nextInt();
ArrayList<Integer> arr = new ArrayList();
for(int i=1; i<str1.length; i++){
for(int j=1; j<str2.length; j++){
arr.add(Integer.parseInt(str1[i])+Integer.parseInt(str2[j]));
}
}
System.out.println(arr);
Collections.sort(arr);
int sum = 0;
for(int i =0; i<n;i++){
sum+=arr.get(i);
}
System.out.println(sum);
}
}
第三题 n 阶方阵和
/*
给出n阶方阵里所有数
求方阵里所有数的和
输入描述:
输入有多个测试用例
每个测试用例第一个第一个整数n n<=1000 表示方阵阶数为n
接下来是n行的数字,每行n个数字用空格隔开
输出描述:
输出一个整数表示n阶方阵的和
例子:
输入
3
1 2 3
2 1 3
3 2 1
输出
18
*/
import java.util.Scanner;
public class Test3 {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int num = Integer.parseInt(sc.nextLine());
//int num = sc.nextInt();//这样写的话,下面 sum+那一行会报错 For input string: ""
int sum = 0;
for(int i = 0; i<num; i++){
String[] split = sc.nextLine().split("\\s+");
for(int j =0; j<num; j++){
sum += Integer.parseInt(split[j]);
}
}
System.out.println(sum);
}
}
第四题 TLV解码
/*
TLV编码是按 Tag Length Value格式进行编码的
一段码流中的信元用tag标识,tag在码流中唯一不重复
length表示信元value的长度 value表示信元的值
码流以某信元的tag开头 ,tag固定占一个字节
length固定占两个字节,字节序为小端序
现给定tlv格式编码的码流以及需要解码的信元tag
请输出该信元的value输入码流的16机制字符中,不包括小写字母
且要求输出的16进制字符串中也不要包含字符字母
码流字符串的最大长度不超过50000个字节输入描述
第一行为第一个字符串 ,表示待解码信元的tag
输入第二行为一个字符串, 表示待解码的16进制码流
字节之间用空格分割
输出描述
输出一个字符串,表示待解码信元以16进制表示的value例子:
输入:
31
32 01 00 AE 90 02 00 01 02 30 03 00 AB 32 31 31 02 00 32 33 33 01 00 CC输出
32 33说明:
需要解析的信源的tag是31
从码流的起始处开始匹配,tag为32的信元长度为1(01 00,小端序表示为1)
第二个信元的tag为90 其长度为2
第三个信元的tag为30 其长度为3
第四个信元的tag为31 其长度为2(02 00)
所以返回长度后面的两个字节即可 为 32 33
*/
import java.util.*;
public class Test4 {
public static void main(String[] args){
Scanner sc = new Scanner(System.in);
String tag = sc.nextLine();
String[] split = sc.nextLine().split("\\s+");
for(int i=0; i<split.length; ){
int len = Integer.parseInt(split[i+2]+split[i+1],16);
if(tag.equals(split[i])){
StringBuilder bu = new StringBuilder();
for(int j=i+3; j<i+3+len;j++){
bu.append(split[j]).append(" ");
}
System.out.println(bu.toString());
break;
}
else{
i+=len+3;
}
}
}
}
第五题 猴子跳台阶 1级和3级(递归的循环写法)
/*
labuladong 书上有提到,大概画了个图,但是尚未完全搞明白一天一只顽猴想要从山脚爬到山顶
途中经过一个有n个台阶的阶梯,但是这个猴子有个习惯,每一次只跳1步或3步
试问?猴子通过这个阶梯有多少种不同的跳跃方式输入描述:
输入只有一个这个数n 0<n<50
此阶梯有多个台阶
输出描述:
有多少种跳跃方式实例:
输入
50
输出
122106097输入
3
输出
2
*/
import java.util.Scanner;
public class Test5 {
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
int n = in.nextInt();
int f1 = 1;
int f2 = 1;
int f3 = 2;
int f4 = n == 1 || n == 2 ? 1 : 2;
for (int i = 4; i <= n; i++) {
f4 = f3 + f1;
f1 = f2;
f2 = f3;
f3 = f4;
}
System.out.println(f4);
in.close();
}
}
第六题 GPU 算力
/*
为了充分发挥Gpu算力,
需要尽可能多的将任务交给GPU执行,
现在有一个任务数组,
数组元素表示在这1s内新增的任务个数,
且每秒都有新增任务,
假设GPU最多一次执行n个任务,
一次执行耗时1s,
在保证Gpu不空闲的情况下,最少需要多长时间执行完成。输入描述
第一个参数为gpu最多执行的任务个数
取值范围1~10000
第二个参数为任务数组的长度
取值范围1~10000
第三个参数为任务数组
数字范围1~10000输出描述
执行完所有任务需要多少秒例子
输入
3
5
1 2 3 4 5
输出
6说明,一次最多执行3个任务 最少耗时6s
例子2
输入
4
5
5 4 1 1 1
输出
5说明,一次最多执行4个任务 最少耗时5s
*/
/*
用 more 变量削峰,一次处理1秒内新增的任务,处理不完的放下一秒一起处理。
*/
import java.util.Scanner;
public class Test6 {
//自己写的
public static void main(String[] args){
Scanner sc = new Scanner(System.in);
int n = Integer.parseInt(sc.nextLine().trim());
int m = Integer.parseInt(sc.nextLine().trim());
String[] str = sc.nextLine().split("\\s+");
int time=0;
int more=0;
for(String i:str){
int j = Integer.parseInt(i);
if(j+more>n)more = more+j-n;
else
more=0;
time++;
}
while(more>0){
more = more-n;
time++;
}
System.out.println(time);
}
}
第七题 身高排序(绝对差值)【考察 list.sort(new Comparator<>(){})】
/*
小明今年升学到了小学1年纪
来到新班级后,发现其他小朋友身高参差不齐
然后就想基于各小朋友和自己的身高差,对他们进行排序
请帮他实现排序
输入描述
第一行为正整数 h和n
0<h<200 为小明的身高
0<n<50 为新班级其他小朋友个数
第二行为n各正整数
h1 ~ hn分别是其他小朋友的身高
取值范围0<hi<200
且n个正整数各不相同输出描述
输出排序结果,各正整数以空格分割
和小明身高差绝对值最小的小朋友排在前面
和小明身高差绝对值最大的小朋友排在后面
如果两个小朋友和小明身高差一样
则个子较小的小朋友排在前面示例一
输入
100 10
95 96 97 98 99 101 102 103 104 105
输出
99 101 98 102 97 103 96 104 95 105说明 小明身高100
班级学生10个 身高分别为
*/
import java.util.ArrayList;
import java.util.Comparator;
import java.util.Scanner;
/*
题目7:重点考察 重写 Comparator 接口的 compare 方法
注意书写格式
new Comparator<T>(){
@override
public int compare(T o1, T o2){
}
}
*/
public class Test7 {
public static void main(String[] args){
Scanner sc = new Scanner(System.in);
String[] str1 = sc.nextLine().split("\\s+");
String[] str2 = sc.nextLine().split("\\s+");
int h = Integer.parseInt(str1[0]);
int n = Integer.parseInt(str1[1]);
ArrayList<Integer> list = new ArrayList<>();
for(String s:str2){
list.add(Integer.parseInt(s));
}
list.sort(new Comparator<Integer>(){
@Override
public int compare(Integer h1,Integer h2){
int d1 = h1-h;
int d2 = h2-h;
d1 = d1>0?d1:-d1;
d2 = d2>0?d2:-d2;
if(d1!=d2) return d1-d2;
else return h1-h2; //Integer 可以直接相减,String 或其它类型自然排序得用 o1.compareTo(o2) 了
}
});
StringBuilder bu = new StringBuilder();
for(int i=0; i<list.size(); i++){
bu.append(list.get(i)).append(" ");
}
System.out.println(bu.toString());
}
}
第八题 区间字符串倒转输出
/*
输入一个英文文章片段
翻转指定区域的单词顺序
标点符号和普通字母一样处理
例如输入字符串 I am a developer.
[0,3]
则输出 developer. a am I输入描述
使用换行隔开3个参数
第一个参数为文章内容 即英文字符串
第二个参数为翻转起始单词下标,下标从0开始
第三个参数为结束单词下标输出描述
翻转后英文文章片段每个单词之间以一个半角空格分割输出
例子
输入
I am a developer.
0
3
输出
I a am developer.输入
hello world!
0
3
输出
world! hello输入字符串可以在前面或者后面包含多个空格
但是翻转后的字符不能包括指定反转区间只有一个单词
或无有效单词
则输出EMPTY
import java.util.Scanner;
/*
题目8 考察反转字符串,主要是区间范围内反转
要用两个index变量
非反转区间的就用 i++
反转区间 j-- (j 提前赋值=end)
*/
public class Test8 {
public static void main(String[] args){
Scanner sc = new Scanner(System.in);
String[] words = sc.nextLine().trim().split("\\s+");
int start = Integer.parseInt(sc.nextLine().trim());
int end = Integer.parseInt(sc.nextLine().trim());
int i=0;
int j=end<(words.length)?end:words.length-1;
StringBuilder bu = new StringBuilder();
String res = "EMPTY";
if(start>=0 && end>0 && start<end && start<words.length){
while(i<words.length){
if(i<start||i>end){
bu.append(words[i++]).append(" ");
}
else if(i>=start && i<=end){
bu.append(words[j--]).append(" ");
i++;
}
res = bu.toString().trim();
}
}
System.out.println(res);
}
}
第九题 购买最多商品【穷举法,TreeSet 排序】
/*
双11众多商品进行打折销售,小明想购买一些自己心意的商品
但由于受购买资金限制,所以他决定从众多心意商品中购买3件
而且想尽可能的花完资金
现在请你设计一个程序帮助小明计算尽可能花费的最大资金额输入描述
第一行为整型数组M 数组长度小于100 数组元素记录单个商品的价格
单个商品价格<1000
第二行输入为购买资金的额度R
R<100000输出描述
输出为满足上述条件的最大花费额度
如果不存在满足上述条件的商品请返回-1例子1
输入
23,26,36,27
78
输出
76例子2
输入
23,30,40
26
输出
-1备注:输入格式正确
*/
import java.util.*;
public class Test9{
public static void main(String[] args){
Scanner sc = new Scanner(System.in);
String[] split = sc.nextLine().split(",");
int total = sc.nextInt();
int[] m = new int[split.length]; //注意开辟数组长度的写法
for(int i=0; i<m.length; i++){
m[i] = Integer.parseInt(split[i]);
}
TreeSet<Integer> ts = new TreeSet<>(); //必须加泛型,不加的话会告警 unsafe operation
for(int i=0;i<m.length;i++){
for(int j=i+1;j<m.length;j++){
for(int k=j+1;k<m.length;k++){
int sum = m[i]+m[j]+m[k];
if(sum<=total){
ts.add(sum);
}
}
}
}
if(0==ts.size()){
System.out.println(-1);
}else{
System.out.println(ts.last());
}
}
}
第十题 字符串排序
/*
给定两个字符串
从字符串2中找出字符串1中的所有字符
去重并按照ASCII码值从小到大排列
输入字符串1长度不超过1024
字符串2长度不超过100字符范围满足ASCII编码要求,按照ASCII由小到大排序
输入描述:
bach
bbaaccddfg
输出
abc2
输入
fach
bbaaccedfg
输出
acf*/
import java.util.Scanner;
import java.util.TreeSet;
public class Test10 {
public static void main(String[] args){
Scanner sc = new Scanner(System.in);
String[] split = sc.nextLine().split("");
String str = sc.nextLine();
TreeSet<String> ts = new TreeSet<>();
for(int i=0; i<split.length; i++){
if(str.contains(split[i])) ts.add(split[i]);
}
for(String t:ts){
System.out.print(t);
}
}
}
第十一题 int 字节和(位运算)
/*
对一个数据a进行分类
分类方法是 此数据a(4个字节大小)的4个字节相加对一个给定值b取模
如果得到的结果小于一个给定的值c则数据a为有效类型
其类型为取模的值
如果得到的结果大于或者等于c则数据a为无效类型比如一个数据a=0x01010101 b=3
按照分类方法计算 (0x01+0x01+0x01+0x01)%3=1
所以如果c等于2 则此a就是有效类型 其类型为1
如果c等于1 则此a是无效类型又比如一个数据a=0x01010103 b=3
按分类方法计算(0x01+0x01+0x01+0x03)%3=0
所以如果c=2则此a就是有效类型 其类型为0
如果c等于0 则此a是无效类型输入12个数据
第一个数据为c 第二个数据为b
剩余10个数据为需要分类的数据请找到有效类型中包含数据最多的类型
并输出该类型含有多少个数据输入描述
输入12个数据用空格分割
第一个数据为c 第二个数据为b
剩余10个数据为需要分类的数据输出描述
请找到有效类型中包含数据最多的类型
并输出该类型含有多少个数据实例:
输入
3 4 256 257 258 259 260 261 262 263 264 265
输出
3
说明
这10个数据4个字节相加后的结果分别是
1 2 3 4 5 6 7 8 9 10
故对4取模的结果为
1 2 3 0 1 2 3 0 1 2
c是3所以012都是有效类型
类型为1和2的有3个数据
类型为0和3的只有两个例子2
输入
1 4 256 257 258 259 260 261 262 263 264 265
输出
2
*/
import java.util.*;
//思路
// split[i] -> sum[i]
// x = sum[i]%b>c
// map.put(x,map.contains(x)?(map.get(x)+1):1)
public class Test11{
public static void main(String[] args){
Scanner sc = new Scanner(System.in);
String[] split = sc.nextLine().split("\\s+");
int c = Integer.parseInt(split[0]);
int b = Integer.parseInt(split[1]);
HashMap<Integer,Integer> map = new HashMap<>();
for(int i=2; i<split.length; i++){
int x = intGetSum( Integer.parseInt(split[i]) ) % b;
if(x < c)
map.put(x,(map.containsKey(x)?(map.get(x)+1):1));
}
int max=0;
for(Integer value:map.values()){
if(value>max)max=value;
}
System.out.println(max);
}
private static int intGetSum(int n){
int sum=0;
for(int i=0;i<4;i++){
sum+=(byte)(n>>(i*8));
}
return sum;
}
}
第十二题 无题目,好像是迷宫
import java.util.*;
public class Test12 {
private static int max = 0;
private static char[][] chars;
public static void main(String[] args) {
/*
3,4
f,m,m,f
f,m,m,f
f,f,f,m
3
*/
Scanner in = new Scanner(System.in);
String[] split = in.nextLine().split(",");
int row = Integer.parseInt(split[0]);
int col = Integer.parseInt(split[1]);
chars = new char[row][col];
for (int i = 0; i < row; i++) {
char[] split1 = in.nextLine().replaceAll(",", "").toCharArray();
for (int j = 0; j < col; j++) {
chars[i][j] = split1[j];
}
}
int i1 = find3(0, 1);
if (i1 > max) max = i1;
System.out.println(max);
in.close();
}
private static int find1(int row, int col) {
if (chars[row][col] != 'm') return 0;
else return 1 + find1(row, col + 1);
}
private static int find2(int row, int col) {
if (chars[row][col] != 'm') return 0;
else return 1 + find2(row + 1, col);
}
private static int find3(int row, int col) {
if (chars[row][col] != 'm') return 0;
else return 1 + find3(row + 1, col + 1);
}
}
第十三题 二叉树存储数组
/*
二叉树也可以用数组来存储
给定一个数组
树的根节点的值储存在下标1
对于储存在下标n的节点,
他的左子节点和右子节点分别储存在下标2*n和2*n+1
并且我们用-1代表一个节点为空
给定一个数组存储的二叉树
试求从根节点到最小的叶子节点的路径
路径由节点的值组成输入描述
输入一行为数组的内容
数组的每个元素都是正整数,元素间用空格分割
注意第一个元素即为根节点的值
即数组的第n元素对应下标n
下标0在树的表示中没有使用
所以我们省略了
输入的树最多为7层输出描述
输出从根节点到最小叶子节点的路径上各个节点的值
由空格分割
用例保证最小叶子节点只有一个例子
输入
3 5 7 -1 -1 2 4
输出
3 7 2例子
输入
5 9 8 -1 -1 7 -1 -1 -1 -1 -1 6
输出
5 8 7 6
*/
import java.util.*;
public class Test13 {
public static void main(String[] args){
/*
给定一个数组存储的二叉树
试求从根节点到最小的叶子节点的路径
路径由节点的值组成
先找到最小节点值,然后 indexOf 找出索引位
然后根据节点生成算法 n,n+1 反推回索引为1的根节点
过程中的值保存起来 如 3 2 1
最后输出时再颠倒一下顺序 1 2 3
*/
Scanner sc = new Scanner(System.in);
String[] split = sc.nextLine().split("\\s+");
//第一步 重建二叉树数组
ArrayList<Integer> list = new ArrayList<>();
list.add(Integer.MAX_VALUE);//二叉树数组 第0位不使用,这里用超大值填充
for(String s:split){
list.add(Integer.parseInt(s)); //二叉树数组重建完毕
}
//第二步 寻找最小叶子结点
int min=Integer.MAX_VALUE;
for(Integer i:list){
if( !i.equals(list.get(1)) && (i!=-1) ){
if(i<min) min = i;
}
}
//第三步 确定最小叶子结点在二叉树数组的下标 index
int indexMin = list.indexOf(min);
//第四步 反推回根节点,获得路径值
ArrayList<Integer> list2 = new ArrayList<>();
for(int i=indexMin; i>0;){
list2.add(list.get(i));
i = i/2;
}
//第五步 颠倒输出
StringBuilder bu = new StringBuilder();
for(int i = list2.size()-1; i>=0 ;i--)
{
bu.append(list2.get(i)).append(" ");
}
System.out.println(bu.toString().trim());
}
}
第十四题 装最多快递
/*
一辆运送快递的货车
运送的快递放在大小不等的长方体快递盒中
为了能够装载更多的快递同时不能让货车超载
需要计算最多能装多少个快递
注:快递的体积不受限制
快递数最多1000个
货车载重最大50000
输入描述
第一行输入每个快递的重量
用英文逗号隔开
如 5,10,2,11
第二行输入货车的载重量
如 20
输出描述
输出最多能装多少个快递
如 3
示例一
输入
5,10,2,11
20
输出
3
*/
第十五题 航天器太阳能板,无图看不懂
/*
给航天器一侧加装长方形和正方形的太阳能板(图中的斜线区域)
需要先安装两个支柱(图中的黑色竖条)
再在支柱的中间部分固定太阳能板
但航天器不同位置的支柱长度不同
太阳能板的安装面积受限于最短一侧的那支支柱的长度现提供一组整型数组的支柱高度数据
假设每个支柱间的距离相等为一个单位长度
计算如何选择两根支柱可以使太阳能板的面积最大输入描述
10,9,8,7,6,5,4,3,2,1
注释,支柱至少有两根,最多10000根,能支持的高度范围1~10^9的整数柱子的高度是无序的
例子中的递减是巧合输出描述
可以支持的最大太阳板面积:(10m高支柱和5m高支柱之间)
25示例1
输入
10,9,8,7,6,5,4,3,2,1
输出
25
备注 10米高支柱和5米高支柱之间宽度为5,高度取小的支柱高度也是5
面积为25
任取其他两根支柱所能获得的面积都小于25 所以最大面积为25*/
第十六题 单词接龙 后一个字符串前缀是前一个字符串后缀
/*
单词接龙的规则是
可用于接龙的单词 首字母必须要与前一个单词的尾字母相同
当存在多个首字母相同的单词时,取长度最长的单词
如果长度也相等,则取字典序最小的单词
已经参与接龙的单词不能重复使用
现给定一组全部由小写字母组成的单词数组
并指定其中一个单词为起始单词
进行单词接龙
请输出最长的单词串
单词串是单词拼接而成的中间没有空格输入描述
输入第一行为一个非负整数
表示起始单词在数组中的索引k
0<=k<N
输入的第二行为非负整数N
接下来的N行分别表示单词数组中的单词输出描述,
输出一个字符串表示最终拼接的单词串示例
0
6
word
dd
da
dc
dword
d输出
worddwordda
说明 先确定起始单词word 在接dword
剩余dd da dc 则取da示例2
4
6
word
dd
da
dc
dword
d输出
dwordda单词个数1<N<20
单个单词的长度 1~30*/
/*题目16单词接龙
TreeSet 确保自然升序
考察 String str.substring(begin index) 取index 到结尾的子串
boolean str.startsWith(str2) 字符串 str是否以 str2 开头
有思路了,就差写了。今天太晚了,先过,回头再写
首字母必须要与前一个单词的尾字母相同(str2.startsWith(str.substr(length-1)))
1 当存在多个首字母相同的单词时,取长度最长的单词
2 如果长度也相等,则取字典序最小的单词(1 2都可以用 TreeSet 一次性解决)
已经参与接龙的单词不能重复使用(用一个单词,就从 list 里删掉它)
输入
起始index
总共单词个数
分行输入单词
输出
接龙后的单词组合字符串,中间无空格
思路:
list 存放输入原始单词列表
*/
import java.util.ArrayList;
import java.util.Scanner;
import java.util.TreeSet;
import java.util.concurrent.BrokenBarrierException;
/**
* Created with IntelliJ IDEA.
* Author: Amos
* E-mail: amos@amoscloud.com
* Date: 2020/11/30
* Time: 12:42
* Description:
*/
public class Demo16 {
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
int k = Integer.parseInt(in.nextLine());
int N = Integer.parseInt(in.nextLine());
ArrayList<String> list = new ArrayList<>();
for (int i = 0; i < N; i++) {
list.add(in.nextLine());
}
StringBuilder builder = new StringBuilder();
String head = list.get(k);
builder.append(head);
list.remove(k);
String tail = head.substring(head.length() - 1);
while (true) {
TreeSet<String> set = new TreeSet<>();
for (int i = 0; i < list.size(); i++) {
String word = list.get(i);
if (word.startsWith(tail)) {
set.add(word);
}
}
if (set.size() == 0) break;
String first = set.pollFirst();
int len = first.length();
String aim = "";
for (String s : set) {
if (s.length() > len) {
len = s.length();
aim = s;
}
}
String into = len != first.length() ? aim : first;
tail = into.substring(into.length() - 1);
builder.append(into);
list.remove(into);
}
System.out.println(builder.toString());
in.close();
}
}
第十七题 第 k 长子串
/*
给定一个字符串
只包含大写字母
求在包含同一字母的子串中
长度第K长的子串
相同字母只取最长的子串输入
第一行 一个子串 1<len<=100
只包含大写字母
第二行为k的值输出
输出连续出现次数第k多的字母的次数例子:
输入
AABAAA
2
输出
1
同一字母连续出现最多的A 3次
第二多2次 但A出现连续3次输入
AAAAHHHBBCDHHHH
3输出
2//如果子串中只包含同一字母的子串数小于k
则输出-1
*/
import java.util.*;
public class Test17 {
public static void main(String[] args){
Scanner sc = new Scanner(System.in);
String str = sc.nextLine();
int k = sc.nextInt();
//第一步 将字符串按照 字母,次数 放入map 映射中
HashMap<Character,Integer> map = new HashMap<>();
char[] chars = str.toCharArray();
char cur=chars[0];
int count=1;
map.put(cur,count);
for(int i=1; i<chars.length; i++){
char c=chars[i];
if(c==cur)count++;
else{
cur = c;
count = 1;
}
map.put(cur,map.containsKey(cur)?(map.get(cur)>count?map.get(cur):count):count);
}
//第二步 按字母出现次数排序
// 2.1先将其转化为 字母-次数 形式的 list 列表
// 2.2然后list.sort(new Comparator(){自定义排序规则})
ArrayList<String> list = new ArrayList<>();
for(Map.Entry<Character,Integer> entry:map.entrySet()){
list.add(entry.getKey()+"-"+entry.getValue());
}
list.sort(new Comparator<String>(){
@Override
public int compare(String o1, String o2){
return o2.split("-")[1].compareTo(o1.split("-")[1]); //如果是 Integer 可以直接相减,String 或其它类型就得用 compareTo 比较大小了
}
});
//第三步 取出 第 k 个
if(k>list.size()){
System.out.println(-1);
}else{
System.out.println(list.get(k-1).split("-")[1]);
}
}
}
第十八题 喊7
/*
喊7 是一个传统的聚会游戏
N个人围成一圈
按顺时针从1-7编号
编号为1的人从1开始喊数
下一个人喊得数字是上一个人喊得数字+1
但是当将要喊出数字7的倍数或者含有7的话
不能喊出 而是要喊过假定N个人都没有失误。
当喊道数字k时
可以统计每个人喊 “过"的次数现给定一个长度n的数组
存储打乱的每个人喊”过"的次数
请把它还原成正确顺序即数组的第i个元素存储编号i的人喊“过“的次数
输入为1行
空格分割的喊过的次数
注意k并不提供k不超过200
数字个数为n
输出描述输出为1行
顺序正确的喊过的次数 空格分割例子
输入
0 1 0
输出
1 0 0只有一次过
发生在7
按顺序编号1的人遇到7 所以100
结束时的k不一定是7 也可以是 8 9
喊过都是100例子
输入
0 0 0 2 1
输出
0 2 0 1 0
一共三次喊过
发生在7 14 17
编号为2 的遇到7 17
编号为4 的遇到14
*/
import java.util.*;
public class Test18 {
/*
7的倍数或含有7
数组 打乱的喊过7次数
请按正确顺序排序
个数 = 人数
index 位置无所谓,刚开始打乱的
HashMap
1 0
2 0
3 0
4 2
5 1
计算总次数,到达总次数就输出顺序累计结果
//第一步 计算总次数
total+=str[i];
//第二步 模拟游戏,符合条件 cnt++,cnt>=total则游戏结束,按顺序输出m
int[] m = new int[str.length];
int cnt=0;
while(cnt<total){
if(cnt/(m[i]+1)==7 || cnt/(m[i]+1)%10==7){
m[i] = m[i]+1;
cnt++;
}
}
*/
public static void main(String[] args){
Scanner sc = new Scanner(System.in);
String[] split = sc.nextLine().split("\\s+");
//第一步 计算总次数
int total = 0; //喊7总次数
for(String s:split){
total+=Integer.parseInt(s);
}
//第二步 模拟游戏,符合条件 cnt++,cnt>=total则游戏结束,按顺序输出m
int[] m = new int[split.length];
int cnt=0; //喊7次数
int pos=0; //位次
for(int i=1; i<=200; i++){
if(pos==m.length)pos=1;
else pos++; //位次从编号1开始到人数上限,然后再重回编号1
if(i%7==0 || i%10==7){
m[pos-1] = m[pos-1]+1;
cnt++;
}
if(cnt==total) break; //喊7次数等于总次数则结束
}
StringBuilder bu = new StringBuilder();
for(int i=0; i<split.length; i++){
bu.append(m[i]).append(" ");
}
System.out.println(bu.toString().trim());
}
}
第十九题 删除出现次数最少字符串
/*
删除字符串中出现次数最少的字符
如果多个字符出现次数一样则都删除例子:
输入
abcdd
字符串中只
输出
dd输入
aabbccdd输出
empty如果都被删除 则换为empty
*/
import java.util.*;
public class Test19 {
public static void main(String[] args){
/*
删除字符串中出现次数最少的字符
如果多个字符出现次数一样则都删除
思路
第一步 建立map<字符,次数>映射
put containsKey()有的话更新该 key 的 value+1;没有的话新插入
第二步 寻找出现次数最少的字符的次数 min
第三步 遍历 map,符合value==min条件的
都将其对应的 key 值从原有字符串中替换为空""(这样还不破坏原有字符串顺序!)
*/
Scanner sc = new Scanner(System.in);
String line = sc.nextLine();
char[] chars = line.toCharArray();
//第一步 建立map<字符,次数>映射
HashMap<Character,Integer> map = new HashMap<>();
for(char c:chars){
map.put(c,map.containsKey(c)?map.get(c)+1:1);
}
//第二步 寻找出现次数最少的字符的次数 min
Integer[] cnts = new Integer[map.size()];
Integer[] n = map.values().toArray(cnts);
Arrays.sort(n);
Integer min = n[0];
//第三步 遍历 map,符合value==min条件的
//都将其对应的 key 值从原有字符串中替换为空""(这样还不破坏原有字符串顺序!)
for(Map.Entry<Character,Integer> entry:map.entrySet()){
if(min.equals(entry.getValue())){
line=line.replaceAll(entry.getKey()+"","");
}
}
if(line.length()==0)System.out.println("empty");
else System.out.println(line);
}
}
第二十题 走到最后一个成员最小步数
/*
一个正整数数组 设为nums
最大为100个成员
求从第一个成员开始正好走到数组最后一个成员所使用的最小步骤数
3 5 9 4 2 6 8 3 5 4 3 9
要求:
1. 第一步 必须从第一元素起 且 1<=第一步步长<len/2 (len为数组长度)
2. 从第二步开始只能以所在成员的数字走相应的步数,不能多不能少,
如果目标不可达返回-1
只输出最小的步骤数量
3. 只能向数组的尾部走不能向回走输入描述:
有正整数数组 空格分割
数组长度<100输出描述 :
正整数 最小步数
不存在输出-1例子:
输入
7 5 9 4 2 6 8 3 5 4 3 9
输出
2
第一个可选步长选择2
从第一个成员7开始走两步到9
第二步:从9经过9个成员到最后例子:
输入
1 2 3 7 1 5 9 3 2 1
输出
-1
*/
import java.util.*;
public class Test20 {
public static void main(String[] args){
/*
思路
第一步 for 循环 1- (length/2-1)
int cnt=1;
第二步 for(i=第一步结果;; ){
i = i + m[i];
cnt++;
if(i>length) {
cnt = 0;
break;
}
if(i=length)break;
}
if(cnt!=0)list.add(cnt);
第三步 list.sort() 取 list.get(0); list.size()==0则返回-1
答案是用 TreeSet set.first() 是取出最低元素
*/
Scanner sc = new Scanner(System.in);
String[] split = sc.nextLine().split("\\s+");
int[] m = new int[split.length];
for(int i=0; i<m.length; i++){
m[i] = Integer.parseInt(split[i]);
}
TreeSet<Integer> set = new TreeSet<>();
//第一步 第一步的 for 循环
for(int i=0;i< (m.length/2)-1 ;i++){
int cnt = 1;
//第二步 for循环按值跳步
for( int j=i; ;){
j = j+m[j];
cnt++;
if(j>m.length-1){ //索引+值 超范围 直接返回。cnt=0作为标志位。
cnt=0;
break;
}
if(j==m.length-1){ //索引+值 正好到达最后一位,bingo 返回。
break;
}
}
if(0!=cnt){
set.add(cnt);
}
}
//第三步 取 set 最小值,如果 set 为空,则输出-1
if(0==set.size()) System.out.println(-1);
else System.out.println(set.first());
}
}
第二十一题(同二十题)
第二十二题 轮流合并新数组
/*
现在有多组整数数组
需要将他们合并成一个新的数组
合并规则从每个数组里按顺序取出固定长度的内容
合并到新的数组
取完的内容会删除掉
如果改行不足固定长度,或者已经为空
则直接取出剩余部分的内容放到新的数组中继续下一行输入描述
第一 行每次读取的固定长度
长度0<len<10
第二行是整数数组的数目
数目 0<num<10000
第3~n行是需要合并的数组
不同的数组用换行分割
元素之间用逗号分割
最大不超过100个元素输出描述
输出一个新的数组,用逗号分割示例1
输入
3
2
2,5,6,7,9,5,7
1,7,4,3,4
输出
2,5,6,1,7,4,7,9,5,3,4,7说明 获得长度3和数组数目2
先遍历第一行 获得2,5,6
再遍历第二行 获得1,7,4
再循环回到第一行获得7,9,5
再遍历第二行获得3,4
再回到第一行获得7示例2
输入
4
3
1,2,3,4,5,6
1,2,3
1,2,3,4
输出
1,2,3,4,1,2,3,1,2,3,4,5,6
*/
import java.util.*;
public class Test22 {
/*
要求 从 n 个数组中,每次读取固定长度
轮流读取,拼接成一个字符串
思路
arraylist<arraylist<String>> list 存储输入的数组
arraylist<String> res 存储拼接后的数组
第一步 输入值存入 list 数组
第二步 list 转到 res 中
第三步 转成StringBuilder输出
*/
public static void main(String[] args){
Scanner sc = new Scanner(System.in);
int len = Integer.parseInt(sc.nextLine());
int num = Integer.parseInt(sc.nextLine());
ArrayList<ArrayList<String>> list = new ArrayList<>();
ArrayList<String> res = new ArrayList<>();
//第一步 输入数据放入list
int total=0;
for(int i=0; i<num; i++){
String[] split = sc.nextLine().split(",");
total+=split.length;
list.add(new ArrayList<String>(Arrays.asList(split)));
}
//第二步 数组拼接后放入 res
while(total!=res.size()){
for(ArrayList<String> strlist:list){
if(0==strlist.size()) continue;
int times = Math.min(strlist.size(),len); //选择取数次数
for(int i=0;i<times;i++){
res.add(strlist.remove(0)); //从原有数据删除+赋值给 res
}
}
}
//第三步 放入 StringBuilder 输出
StringBuilder bu = new StringBuilder();
for(int i=0; i<res.size()-1; i++){
bu.append(res.get(i)).append(",");
}
bu.append(res.get(res.size()-1));
System.out.println(bu.toString());
}
}
第二十三题 磁盘容量排序
/*
磁盘的容量单位常用的有
M G T
他们之间的换算关系为 1T =1024G 1G=1024M
现在给定n块磁盘的容量,请对他们按从小到大的顺序进行稳定排序
例如给定5块盘的容量
5
1T
20M
3G
10G6T
3M12G9M
排序后的结果为
20M
3G
3M 12G 9M
1T,10G 6T
注意单位可以重复出现
上述3M 12G 9M表示的容量即为 3M 12G 9M 和12M 12G相等
输入描述、
输入第一行包含一个整数n
2<=n<=100 表示磁盘的个数
接下来的n行
每行一个字符串
2<长度<30
表示磁盘的容量
由一个或多个格式为MV的子串组成
其中m表示容量大小
v表示容量单位
例如20M 1T
磁盘容量的范围1~1024的正整数
单位 M G T
输出n行
表示n块磁盘容量排序后的结果实例
输入
3
1G
2G
1024M
输出
1G
1024M
2G
说明:稳定排序要求相等值保留原来位置示例2
3
2G4m
3M2G
1T
输出
3M2G
2G4M
1T
*/
import java.util.*;
public class Test23 {
/*
关键点,1单位换算 拆分前后单位,还好单位只有1位,好拆分。
麻烦了,可能有多个 mV 【这里才是重点】
2稳定排序 冒泡算法 Arrays.sort()也可以【答案还用 list.sort】
String[] 数组存储
思路:
第一步 存 list
第二步 list.sort,new Comparator<>(){}
第三步 calc 计算 将mV统一化
*/
public static void main(String[] args){
Scanner sc = new Scanner(System.in);
int n = Integer.parseInt(sc.nextLine());
ArrayList<String> list = new ArrayList<>();
for(int i=0; i<n; i++){
list.add(sc.nextLine());
}
list.sort(new Comparator<String>(){
@Override
public int compare(String o1,String o2){
return calc(o1)-calc(o2);
}
});
for(String s:list){
System.out.println(s);
}
}
private static int calc(String line){
int size=0;
int len=0;
String upper = line.toUpperCase();
String[] split = line.split("[A-Z]");
for (String s : split) {
len += s.length();
String v = upper.substring(len, len + 1);
switch (v) {
case "M":
size += Integer.parseInt(s);
break;
case "G":
size += Integer.parseInt(s) * 1024;
break;
case "T":
size += Integer.parseInt(s) * 1024 * 1024;
break;
default:
break;
}
}
return size;
}
}