华为机考
051 【数组组成的最小数字】
给定一个整型数组,请从该数组中选择3个元素组成最小数字并输出(如果数组长度小于3,则选择数组中所有元素来组成最小数字)。
输入描述:
一行用半角逗号分割的字符串记录的整型数组,0 < 数组长度 <= 100,0 < 整数的取值范围 <= 10000。
输出描述:
由3个元素组成的最小数字,如果数组长度小于3,则选择数组中所有元素来组成最小数字。
示例1
输入
21,30,62,5,31
输出
21305
说明
数组长度超过3,需要选3个元素组成最小数字,21305由21,30,5三个元素组成的数字,为所有组合中最小的数字
示例2
输入
5,21
输出
215
说明
数组长度小于3, 选择所有元素来主城最小值,215为最小值。
//思路:
//1、大于3各数的数组,从其中选择3各最小的数,组合排序可以得到最小的数
//2、小于3各数,组合排序即可
//3、可以根据首位进行排序
052 【水仙花数】
所谓水仙花数,是指一个n位的正整数,其各位数字的n次方和等于该数本身。例如153是水仙花数,153是一个3位数,并且153 = 111 + 555 + 333
输入描述:
第一行输入一个整数n,表示一个n位的正整数。n在3到7之间,包含3和7。[3,7]
第二行输入一个正整数m,表示需要返回第m个水仙花数。
输出描述:
返回长度是n的第m个水仙花数。个数从0开始编号。
若m大于水仙花数的个数,返回最后一个水仙花数和m的乘积。
若输入不合法,返回-1。
示例1
输入
3 0
输出
153
说明
153是第一个水仙花数
示例2
输入
9
1
输出
-1
说明
9超出范围
public class ZT02 {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int count = Integer.parseInt(sc.nextLine());//[3,7]
int num = Integer.parseInt(sc.nextLine());
if (count< 3 || count> 7){
System.out.println(-1);
return;
}//3 100 4 1000
int start = 1;
for (int i = 1; i < count; i++) {
start *= 10;
}
int end = start *10 -1;
int times = 0;
for (int i = start; i < end; i++) {
if (checkFlower(i)){
if (times++ == num) {
System.out.println(i);
return;
}
}
}
System.out.println(-1);
}
private static boolean checkFlower(int num){
int temp = num;
int total = 0;
while (temp > 0){
int wei = temp%10;
total += wei *wei * wei;
temp /=10;
}
return total == num;
}
}
053 【素数之积】
RSA加密算法在网络安全世界中无处不在,它利用了极大整数因数分解的困难度,数据越大,安全系数越高,给定一个32位正整数,请对其进行因数分解,找出是哪两个素数的乘积。
输入描述:
一个正整数num
0 < num <= 2147483647
输出描述:
如果成功找到,以单个空格分割,从小到大输出两个素数,分解失败,请输出-1 -1
示例1
输入
15
输出
3 5
说明
因数分解后,找到两个素数3和5,使得3*5=15,按从小到大排列后,输出3 5
示例2
输入
27
输出
-1 -1
说明
通过因数分解,找不到任何素数,使得他们的乘积为27,输出-1 -1
public class ZT53 {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int target = sc.nextInt();//[0,2147483647]
int max = target;
for (int i = 3; i <= max; i++) {
//先判断能不能被target整除
if (target % i == 0){
max = target / i;
if (checkSu(i) && checkSu(target/i)){
System.out.println(i + " " + target/i);
return;
}
}
}
System.out.println(-1 + " " + -1);
}
//素数是指除了1和本身不能被其他所有数整除
private static boolean checkSu(int num){
for (int i = 2; i < num; i++) {
if (num % i == 0){
return false;
}
}
return true;
}
}
054 【太阳能板最大面积】
给航天器一侧加装长方形或正方形的太阳能板(图中的红色斜线区域),需要先安装两个支柱(图中的黑色竖条),再在支柱的中间部分固定太阳能板。但航天器不同位置的支柱长度不同,太阳能板的安装面积受限于最短一侧的那根支柱长度。如图:
现提供一组整形数组的支柱高度数据,假设每根支柱间距离相等为1个单位长度,计算如何选择两根支柱可以使太阳能板的面积最大。
输入描述:
10,9,8,7,6,5,4,3,2,1
注:支柱至少有2根,最多10000根,能支持的高度范围1~10^9的整数。柱子的高度是无序的,例子中递减只是巧合。
输出描述:
可以支持的最大太阳能板面积:(10米高支柱和5米高支柱之间)
25
示例1
输入
10,9,8,7,6,5,4,3,2,1
输出
25
备注:
10米高支柱和5米高支柱之间宽度为5,高度取小的支柱高也是5,面积为25。任取其他两根支柱所能获得的面积都小于25。所以最大的太阳能板面积为25。
055 【停车场车辆统计】
特定大小的停车场,数组cars[]表示,其中1表示有车,0表示没车。车辆大小不一,小车占一个车位(长度1),货车占两个车位(长度2),卡车占三个车位(长度3),统计停车场最少可以停多少辆车,返回具体的数目。
输入描述:
整型字符串数组cars[],其中1表示有车,0表示没车,数组长度小于1000。
输出描述:
整型数字字符串,表示最少停车数目。
示例1
输入
1,0,1
输出
2
说明
1个小车占第1个车位
第二个车位空
1个小车占第3个车位
最少有两辆车
示例2
输入
1,1,0,0,1,1,1,0,1
输出
3
说明
1个货车占第1、2个车位
第3、4个车位空
1个卡车占第5、6、7个车位
第8个车位空
1个小车占第9个车位
最少3辆车
public class ZT55 {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
String[] split = sc.nextLine().split(",");
//连续的2个1可以是1个 连续三个1可以是1个
int total = 0;
int tem = 0;
for (int i = 0; i < split.length; i++) {
if (Integer.parseInt(split[i]) == 1){
tem++;
}else {
if (tem != 0){
total += calcMin(tem);
}
tem = 0;
}
}
total += calcMin(tem);
System.out.println(total);
}
private static int calcMin(int num){
//6 -> 2
int total = 0;
while (num >= 3){//有多少3 除掉多少3
num -= 3;
total++;
}
while (num >= 2){//有多少3 除掉多少3
num -= 2;
total++;
}
total += num;
return total;
}
}
056 【统计射击比赛成绩】
给定一个射击比赛成绩单,包含多个选手若干次射击的成绩分数,请对每个选手按其最高3个分数之和进行降序排名,输出降序排名后的选手ID序列。条件如下:
1、一个选手可以有多个射击成绩的分数,且次序不固定。
2、如果一个选手成绩少于3个,则认为选手的所有成绩无效,排名忽略该选手。
3、如果选手的成绩之和相等,则成绩之和相等的选手按照其ID降序排列。
输入描述:
输入第一行,一个整数N,表示该场比赛总共进行了N次射击,产生N个成绩分数(2<=N<=100)。
输入第二行,一个长度为N整数序列,表示参与每次射击的选手ID(0<=ID<=99)。
输入第三行,一个长度为N整数序列,表示参与每次射击的选手对应的成绩(0<=成绩<=100)。
输出描述:
符合题设条件的降序排名后的选手ID序列。
示例1
输入
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
说明
该场射击比赛进行了13次,参赛的选手为{3,4,5,7}。
3号选手成绩:53,80,55,最高3个成绩的和为:80+55+53=188。
4号选手成绩:24,39,76,66,最高3个成绩的和为:76+66+39=181。
5号选手成绩:53,80,55,最高3个成绩的和为:80+55+53=188。
7号选手成绩:68,16,100,最高3个成绩的和为:100+68+16=184。
比较各个选手最高3个成绩的和,有3号=5号>7号>4号,由于3号和5号成绩相等且ID号5>3,所以输出为:5,3,7,4
public class ZT56 {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int count = Integer.parseInt(sc.nextLine());
String[] turnList = sc.nextLine().split(",");
String[] scores = sc.nextLine().split(",");
List<Player> plays = new ArrayList<>();
Map<Integer,Integer> map= new HashMap<>();
int tempCount = 0;
//获取成绩
for (int i = 0; i < count; i++) {
int idx = Integer.parseInt(turnList[i]);
List<Integer> li = new ArrayList<>();
li.add(Integer.parseInt(scores[i]));
Player pls = new Player(idx,li);
if (plays.contains(pls)) {
plays.get(map.get(idx)).list.add(Integer.parseInt(scores[i]));
}else{
map.put(idx,tempCount++);
plays.add(pls);
}
}
//整理成绩
for (int i = 0; i < plays.size(); i++) {
Player player = plays.get(i);
List<Integer> list = player.list;
list.sort((a0,b0) -> b0 -a0);//逆序
int total = 0;
for (int j = 0; j < 3; j++) {
total += list.get(j);
}
player.setScore(total);
}
plays.sort(null);
for (int i = 0; i < plays.size(); i++) {
if (i == plays.size() -1){
System.out.print(plays.get(i).idx);
}else {
System.out.print(plays.get(i).idx + ",");
}
}
}
static class Player implements Comparable<Player>{
private int idx;
private List<Integer> list;
private int score;
public void setScore(int score) {
this.score = score;
}
public Player(int idx, List<Integer> list) {
this.idx = idx;
this.list = list;
}
@Override
public boolean equals(Object obj) {
Player ply = (Player)obj;
return ply.idx == this.idx;
}
@Override
public int compareTo(Player ply) {
if (ply.score != this.score){
return ply.score - this.score;
}else {
return ply.idx - this.idx;
}
}
}
}
057 【完全二叉树非叶子部分后序遍历】
给定一个以顺序储存结构存储整数值的完全二叉树序列(最多1000个整数),请找出此完全二叉树的所有非叶子节点部分,然后采用后序遍历方式将此部分树(不包含叶子)输出。
1、只有一个节点的树,此节点认定为根节点(非叶子)。
2、此完全二叉树并非满二叉树,可能存在倒数第二层出现叶子或者无右叶子的情况
其他说明:二叉树的后序遍历是基于根来说的,遍历顺序为:左-右-根 根输出
输入描述:
一个通过空格分割的整数序列字符串
输出描述:
非叶子部分树结构
示例1
输入
1 2 3 4 5 6 7
输出
2 3 1
说明
找到非叶子部分树结构,然后采用后续遍历输出
备注:
输出数字以空格分隔
public class ZT57Tree {
private static List<TreeNode> nodes = new ArrayList<>();
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
String[] input = sc.nextLine().split(" ");
int[] arr = new int[input.length+1];
for (int i = 1; i <= input.length; i++) {
arr[i] = Integer.parseInt(input[i-1]);
}
buildTree(arr);
//检查叶子节点
for (int i = 0; i < nodes.size(); i++) {
int degree = 0;
if (nodes.get(i).left != null){
degree++;
}
if (nodes.get(i).right != null){
degree++;
}
nodes.get(i).degree = degree;
}
afterPrint(nodes.get(1));
}
private static void buildTree(int[] arr){
nodes.add(new TreeNode(0,null,null));
//先将所有的节点放到数组中
for (int i = 1; i < arr.length; i++) {
nodes.add(new TreeNode(arr[i],null,null));
}
for (int i = 1; i < nodes.size(); i++) {
if (2 * i < nodes.size()){
nodes.get(i).left = nodes.get(2 * i);
}
if (2 * i +1 < nodes.size()){
nodes.get(i).right = nodes.get(2 * i +1);
}
}
}
private static void print(TreeNode node){
//只输出非叶子节点
if (node.degree != 0){
System.out.println(node.val);
}
}
//前序遍历 根[根输出] 左 右
private static void prePrint(TreeNode node){
print(node);
if (node.left != null){
prePrint(node.left);
}
if (node.right != null){
prePrint(node.right);
}
}
//中序遍历 左 根[根输出] 右
private static void middlePrint(TreeNode node){
if (node.left != null){
middlePrint(node.left);
}
print(node);
if (node.right != null){
middlePrint(node.right);
}
}
//后续遍历 左-右-根[根输出]
private static void afterPrint(TreeNode node){
if (node.left != null){
afterPrint(node.left);
}
if (node.right != null){
afterPrint(node.right);
}
print(node);
}
private static class TreeNode{
private int degree;
private int val;
private TreeNode left;
private TreeNode right;
public TreeNode(int val, TreeNode left, TreeNode right) {
this.val = val;
this.left = left;
this.right = right;
}
}
}
058 【玩牌高手】
给定一个长度为n的整型数组,表示一个选手在n轮内可选择的牌面分数。选手基于规则选牌,请计算所有轮结束后其可以获得的最高总分数。选择规则如下:
1、在每轮里选手可以选择获取该轮牌面,则其总分数加上该轮牌面分数,为其新的总分数。
2、选手也可不选择本轮牌面直接跳到下一轮,此时将当前总分数还原为3轮前的总分数,若当前轮次小于等于3(即在第1、2、3轮选择跳过轮次),则总分数置为0。
3、选手的初始总分数为0,且必须依次参加每一轮。
输入描述:
第一行为一个小写逗号分割的字符串,表示n轮的牌面分数,1<= n <=20。
分数值为整数,-100 <= 分数值 <= 100。
不考虑格式问题。
输出描述:
所有轮结束后选手获得的最高总分数。
示例1
输入
1,-5,-6,4,3,6,-2
输出
11
说明
总共有7轮牌面。
第一轮选择该轮牌面,总分数为1。
第二轮不选择该轮牌面,总分数还原为0。
第三轮不选择该轮牌面,总分数还原为0。
第四轮选择该轮牌面,总分数为4。
第五轮选择该轮牌面,总分数为7。
第六轮选择该轮牌面,总分数为13。
第七轮如果不选择该轮牌面,则总分数还原到3轮1前分数,即第四轮的总分数4,如果选择该轮牌面,总分数为11,所以选择该轮牌面。
因此,最终的最高总分为11。
059 【相对开音节】
相对开音节构成的结构为辅音+元音(aeiou)+辅音(r除外)+e,常见的单词有bike、cake等。
给定一个字符串,以空格为分隔符,反转每个单词中的字母,若单词中包含如数字等其他非字母时不进行反转。
反转后计算其中含有相对开音节结构的子串个数(连续的子串中部分字符可以重复)。
输入描述:
字符串,以空格分割的多个单词,字符串长度<10000,字母只考虑小写
输出描述:
含有相对开音节结构的子串个数,注:个数<10000
示例1
输入
ekam a ekac
输出
2
说明
反转后为 make a cake 其中make、cake为相对开音节子串,返回2
示例2
输入
!ekam a ekekac
输出
2
说明
反转后为!ekam a cakeke 因!ekam含非英文字符所以未反转,其中 cake、keke为相对开音节子串,返回2
public class ZT59 {
public static void main(String[] args) {
Scanner sc =new Scanner(System.in);
String[] input = sc.nextLine().split(" ");
int total = 0;
for (int i = 0; i < input.length; i++) {
String content = input[i];
boolean flag = true;
for (int j = 0; j < content.length(); j++) {
if (content.charAt(j) < 'a' || content.charAt(j)> 'z'){
flag = false;
break;
}
}
if (flag){
total += checkKai(content);
}
}
System.out.println(total);
}
private static int checkKai(String str){
String strTemp = "";
for (int i = str.length()-1; i >=0 ; i--) {
strTemp += str.charAt(i);
}
int left = 0;
int right = 0;
int total = 0;
String tem = "";
while (right<=str.length()){
tem = strTemp.substring(left,right);
if (tem.length() < 4 ){
right++;
continue;
}
if (checkTrue(tem)) {
total++;
}
left++;
right++;
}
return total;
}
private static boolean checkTrue(String str){
//辅音+元音(aeiou)+辅音(r除外)+e blame
if (!yuanyin.contains(str.charAt(0)) && 'e' == str.charAt(str.length()-1)){//首位是辅音 末尾是元音
int temYuan = 0;
for (int i = 1; i < str.length()-1; i++) {//中间2位或3位
if (yuanyin.contains(str.charAt(i))){
temYuan = i;
}
if (temYuan!= 0 && !yuanyin.contains(str.charAt(i)) && str.charAt(i) != 'r' && i> temYuan){
return true;
}
}
}
return false;
}
private static List<Character> yuanyin = new ArrayList<>();
static {
char[] f1 = {'a','e','i','o','u'};
for (int i = 0; i < f1.length; i++) {
yuanyin.add(f1[i]);
}
}
}
060 【消消乐游戏】
游戏规则:输入一个只包含英文字母的字符串,字符串中的两个字母如果相邻且相同,就可以消除。
在字符串上反复执行消除的动作,直到无法继续消除为止,此时游戏结束。
输出最终得到的字符串长度。
输入描述:
输入原始字符串 str ,只能包含大小写英文字母,字母的大小写敏感, str 长度不超过100。
输出描述:
输出游戏结束后,最终得到的字符串长度
示例1
输入
gg
输出
0
说明
gg 可以直接消除,得到空串,长度为0
示例2
输入
mMbccbc
输出
3
说明
在 mMbccbc 中,可以先消除 cc ;此时字符串变成 mMbbc ,可以再消除 bb ;此时字符串变成 mMc ,此时没有相邻且相同的字符,无法继续消除。最终得到的字符串为 mMc ,长度为3
备注:
输入中包含 非大小写英文字母 时,均为异常输入,直接返回 0
public class ZT60 {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
String input = sc.nextLine();
while (true){
char pre = input.charAt(0);
boolean flag = false;
for (int i = 1; i < input.length(); i++) {
if (input.charAt(i) == pre){
input = input.substring(0,i-1) + input.substring(i+1);
flag = true;
break;
}else {
pre = input.charAt(i);
}
}
if (!flag || input.length() == 0){
System.out.println(input.length());
return;
}
}
}
}