1、最远足迹问题
题目
某探险队对地下洞穴进行探险。
探险队成员在进行探险什务时,随身携带的记录器会不定期地记录自身的坐标,但在记录的间隙中也会记录其他数据。
探索工作结束后,探险队需要获取到某成员在探险过程中相对于探险队总部的最远的足迹位置。
仪器记录坐标时,坐标的数据格式为(x,y),如(1,2)、(100,200),其中 0<x<1000,0<y<1000。
同时存在非法坐标,如(011)、(1,01)、(0,100)属于非法坐标。
设定探险队总部的坐标为(0,0),某位置相对总部的距离为:xx+yy。
若两个座标的相对总部的距离相同,则第一次到达的坐标为最远的足迹。
若记录仪中的坐标都不合法,输出总部坐标(0,0)。
备注:
不需要考虑双层括号嵌套的情况,比如 sfsdfsd((1,2))。
# 测试用例1
# 输入
ferga13fdsf3(100,200)f2r3rfasf(300,400)
# 输出
(300,400)
# 测试用例2
# 输入
ferg(3,10)a13fdsf3(3,4)f2r3rfasf(5,10)
# 输出
(5,10)
解题思路
坐标距离总部的距离=xx + yy,所以关键就是从字符串中,提取合法的(x, y),比取出x、y的值,然后算出距离,最后排序输出最大的。
所以这是一道操作字符串的题目,我是通过逐个遍历,定位每一组’(‘、’)'的下标,放入list<list>中,然后遍历list,用String的split按照逗号分割出两个坐标,算距离。
java代码
private static void queryMethod(String params){
int leftIndex = 0;
int rightIndex = 0;
List<List<Integer>> all = new ArrayList<>();
char[] chars = params.toCharArray();
for (int i = 0; i < chars.length; i++) {
if('('==(chars[i])){
leftIndex = i+1;
}else if(')'==(chars[i])){
rightIndex = i;
String[] split = params.substring(leftIndex, rightIndex).split(",");
int left = Integer.parseInt(split[0]);
int right = Integer.parseInt(split[1]);
if(split[0].charAt(0)!='0' && split[1].charAt(0)!='0' && left>0 && left<1000 && right>0 && right<1000){
List<Integer> abList = new ArrayList<>();
abList.add(left);
abList.add(right);
all.add(abList);
}
}
}
if (all.size()>0){
all.sort((a, b) -> {
int ax = a.get(0) * a.get(0) + a.get(1) * a.get(1);
int bx = b.get(0) * b.get(0) + b.get(1) * b.get(1);
if(ax >= bx){
return -1;
}else {
return 1;
}
});
System.out.println("(" + all.get(0).get(0) + "," + all.get(0).get(1) + ")");
}else {
System.out.println("(0,0)");
}
}
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
String params = sc.nextLine();
if (params==null || params.length()<1){
System.out.println("(0,0)");
}
queryMethod(params);
}
2、射击比赛
题目
给定一个射击比赛成绩单,包含多个选手若干次射击的成绩分数,请对每个选手按其最高三个分数之和进行降序排名,输出降序排名后的选手 ID 序列。
条件如下:
1.一个选手可以有多个射击成绩的分数、且次序不固定
2.如果一个选手成绩小于三个则认为选手的所有成绩无效排名忽略该选手
3.如果选手的成绩之和相等,则成绩相等的选手按照其 ID 降序排列
输入
输入第一行:一个整数 N
表示该场比赛总共进行了N次射击,产生N个成绩分数,2<=N<=100;
输入第二行:一个长度为 N 的整数序列,表示参与本次射击的选手id,8 <= ID <= 99;
输入第三行是长度为N的整数序列,表示参与每次射击的选手对应的成绩0<= 成绩<= 100
输出
符合题设条件的降序排名后的选手 ID 序列
测试用例
# 输入
13
3,3,7,4,4,4,4,7,7,3,5,5,5
53,80,68,24,39,76,66,16,100,55,53,80,55
# 输出
5,3,7,4
解题思路
1)用数组接收入参,然后按(id,list<成绩>)放入map中;
2)遍历map,把成绩个数大于等于3的放入list<list>中,内层integer放id、总成绩;
3)对list按成绩、id排序,降序输出;
java代码
public static void main(String[] args) {
try {
Scanner sc = new Scanner(System.in);
int num = Integer.parseInt(sc.nextLine());
String[] idStrs = sc.nextLine().split(",");
String[] scoreStrs = sc.nextLine().split(",");
Map<Integer, List<Integer>> idScoreMap = new HashMap<>();
for (int i = 0; i < idStrs.length; i++) {
int id = Integer.parseInt(idStrs[i]);
int score = Integer.parseInt(scoreStrs[i]);
if(score<0 || score>100){
continue;
}
if(idScoreMap.containsKey(id)){
idScoreMap.get(id).add(score);
}else {
List<Integer> scoreList = new ArrayList<>();
scoreList.add(score);
idScoreMap.put(id, scoreList);
}
}
List<List<Integer>> allList = new ArrayList<>();
idScoreMap.forEach((id, scores) -> {
if(scores.size() >= 3){
Collections.sort(scores);
int scoreSum = scores.get(scores.size()-1) + scores.get(scores.size()-2) + scores.get(scores.size()-3);
List<Integer> list = new ArrayList<>();
list.add(id);
list.add(scoreSum);
allList.add(list);
}
});
allList.sort((a, b) -> {
if (!a.get(1).equals(b.get(1)) && a.get(1).compareTo(b.get(1))>0) {
return -1;
}else if(a.get(1).equals(b.get(1)) && a.get(0).compareTo(b.get(0))>0){
return -1;
}
return 1;
});
StringBuffer sb = new StringBuffer();
for (List<Integer> list : allList) {
sb.append(list.get(0)).append(",");
}
sb.deleteCharAt(sb.length()-1);
System.out.println(sb.toString());
}
} catch (Exception e) {
e.printStackTrace();
System.out.println("error");
}
3、篮球争霸-最多MVP
题目
在篮球赛对抗赛中,某战队希望每个队员都能拿到 MVP,MVP 的条件是单场最高分获得者,且mvp可以并列;所以宇宙战队决定在比赛中尽可能让更多队员上场,并且让所有得分的选手得分都相同,然而比赛过程中的每1分钟的得分都只能由某一个人包揽。
输入
第一行为一个数字t,表示有得分的分钟数,1≤t≤50
第二行为t个数字,代表每一分钟的得分p,1≤t≤50
输出
输出有得分的队员都是 MVP 时,最少的 MVP 得分
示例一
# 输入
9
5 2 1 5 2 1 5 2 1
# 输出
6
解题思路
当得分的队员尽量多、且都一样时,mvp得分最少;
得分队员最多为t个、即每分钟一个人得分,且每分钟得分相同;
由大到小穷举每一个可能的队员数n,就可得到每个队员的得分subsum=sum / n,如果sum能除清n,证明这个n有验证的必要。
然后,问题就转换为,将一个数组array,分割为n个小数组,且每个数组的和均为sum/n。
这个问题比较经典,我们专门写一个方法来实现。
为了方便解释这个方法的思路,我假设每个数组元素是一个质量为array[i]的小球,我们要把它们放入n个桶里面,每放一个检查桶里的总质量是否小于等于subsum,如果小于等于就接着放下一个小球,如果大于证明当前这种方法不行、把球取出尝试放入下一个桶…
直到所有的球都放入桶,那就是把数列成功分为n个和相等的子数列了。
java代码
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int t = sc.nextInt();
int[] scores = new int[t];
int sum = 0;
for (int i = 0; i < t; i++) {
scores[i] = sc.nextInt();
sum += scores[i];
}
//逆序排,提高检查效率,不加也能实现功能
Arrays.sort(scores);
int a = 0;
int b = scores.length-1;
while (a < b){
int num = scores[a];
scores[a] = scores[b];
scores[b] = num;
a++;
b--;
}
for (int j = t; j > 1; j--) {
if(sum % j == 0 && check(scores, 0, new int[j], sum/j)){
System.out.println(sum/j);
return;
}
}
System.out.println(sum);
}
private static boolean check(int[] scores, int index, int[] group, int subSum){
if(scores.length == index) return true;//index最多length-1,当index==lenth,说明所有元素都已放完;所有元素都放完,就返回true
int selected = scores[index];
for (int k = 0; k < group.length; k++) {
if(k>0 && group[k] == group[k-1]) continue;
group[k] += selected;
if(group[k] <= subSum) {
if(check(scores, index + 1, group, subSum)) return true;
}
group[k] -= selected;
}
return false;
}
4、水仙花数
题目
给定一个非空字符串 s,将该字符串分割只成一些子串,使每个子串的 ASCI 码值的和均为水仙花数。
1.若分割不成功则返回 0
2.若分割成功且分割结果不唯一则返回 -1
3.若分割成功且分割结果唯一则返回分割后子串的数目
输入
输入字符串的最大长度为 200
输出
根据题目中的情况返回响应结果
测试用例1
# 输入
abc
# 输出
0
测试用例2
# 输入
f3@d5a8
# 输出
-1
测试用例3