华为机考
021 【喊7的次数重排】
喊7是一个传统的聚会游戏,N个人围成一圈,按顺时针从1到N编号。编号为1的人从1开始喊数,下一个人喊的数字为上一个人的数字加1,但是当将要喊出来的数字是7的倍数或者数字本身含有7的话,不能把这个数字直接喊出来,而是要喊"过"。假定玩这个游戏的N个人都没有失误地在正确的时机喊了"过",当喊到数字K时,可以统计每个人喊"过"的次数。
现给定一个长度为N的数组,存储了打乱顺序的每个人喊"过"的次数,请把它还原成正确的顺序,即数组的第i个元素存储编号i的人喊"过"的次数。
输入描述:
输入为一行,为空格分隔的喊"过"的次数,注意K并不提供,K不超过200,而数字的个数即为N。
输出描述:
输出为一行,为顺序正确的喊"过"的次数,也由空格分隔。
示例1:
输入
0 1 0
输出
1 0 0
说明
一共只有一次喊"过",那只会发生在需要喊7时,按顺序,编号为1的人会遇到7,故输出1 0 0。注意,结束时的K不一定是7,也可以是8、9等,喊过的次数都是1 0 0。
示例2:
输入
0 0 0 2 1
输出
0 2 0 1 0
说明
一共有三次喊"过",发生在7 14 17,按顺序,编号为2的人会遇到7 17,编号为4的人会遇到14,故输出0 2 0 1 0。
public class ZT21 {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
String[] input = sc.nextLine().split(" ");
int[] arr = new int[input.length+1];
int total = 0;
for (int i = 0; i < input.length; i++) {
total += Integer.parseInt(input[i]);
}
int temp = 0;
for (int i = 1; i < 200; i++) {
if (checkSeven(i)){
arr[i% input.length]++;
temp++;
}
if (temp>= total){
break;
}
}
for (int i = 1; i < arr.length; i++) {
System.out.print(arr[i] + " ");
}
//7 14 17 21 27 28
}
private static boolean checkSeven(int num){
//1、是不是7的倍数
if (num % 7 == 0){
return true;
}
//2、是不是数字包含7 -> 拆解所有位
while (num > 0){
int wi = num % 10;
if (wi == 7){
return true;
}
num /= 10;
}
return false;
}
}
022 【猴子爬山】
一天一只顽猴想去从山脚爬到山顶,途中经过一个有个N个台阶的阶梯,但是这猴子有一个习惯: 每一次只能跳1步或跳3步,试问猴子通过这个阶梯有多少种不同的跳跃方式?
输入描述:
输入只有一个整数N(0<N<=50)此阶梯有多少个阶梯
输出描述:
输出有多少种跳跃方式(解决方案数)
示例1:
输入
50
输出
122106097
示例2:
输入
3
输出
2
public class ZT22 {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int input = sc.nextInt();
System.out.println(calcCount(input));
}
private static int calcCount(int step){
//只剩一个台阶了
if (step < 3){
return 1;
}
//剩下的场景都需要分成当前跳1步或者跳3步
return calcCount(step -1) + calcCount( step -3);
}
}
023 【滑动窗口最大和】
有一个N个整数的数组,和一个长度为M的窗口,窗口从数组内的第一个数开始滑动直到窗口不能滑动为止,每次窗口滑动产生一个窗口和(窗口内所有数的和),求窗口滑动产生的所有窗口和的最大值。
输入描述:
第一行输入一个正整数N,表示整数个数。(0<N<100000)
第二行输入N个整数,整数的取值范围为[-100,100]。
第三行输入一个正整数M,M代表窗口大小,M<=100000,且M<=N。
输出描述:
窗口滑动产生的所有窗口和的最大值。
示例1:
输入
6
10 20 30 15 23 12
3
输出
68
说明
窗口长度为3,窗口滑动产生的窗口和分别为10+20+30=60,20+30+15=65,30+15+23=68,15+23+12=50,所以窗口滑动产生的所有窗口和的最大值为68。
public class ZT23 {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int count = Integer.parseInt(sc.nextLine());
String[] input = sc.nextLine().split(" ");
int windows = Integer.parseInt(sc.nextLine());
int[] arr = new int[count];
for (int i = 0; i < count; i++) {
arr[i] = Integer.parseInt(input[i]);
}
int left = 0;
int right = 0;
int total = 0;
int max = 0;
while (right<count){
total += arr[right];
if (right - left < windows){
right++;
}else {
total -= arr[left];
left++;
right++;
}
max = Math.max(max,total);
}
System.out.println(max);
}
}
024 【火星文计算】
已知火星人使用的运算符号为#;KaTeX parse error: Expected 'EOF', got '#' at position 17: …其与地球人的等价公式如下: x#̲y=2*x+3*y+4 xy=3x+y+2
1、其中x、y是无符号整数
2、地球人公式按C语言规则计算
3、火星人公式中,KaTeX parse error: Expected 'EOF', got '#' at position 7: 的优先级高于#̲,相同的运算符,按从左到右的顺…)组成的计算表达式。例如:123#4$5#67$78。
1、用例保证字符串中,操作数与操作符之间没有任何分隔符。
2、用例保证操作数取值范围为32位无符号整数。
3、保证输入以及计算结果不会出现整型溢出。
4、保证输入的字符串为合法的求值报文,例如:123#4$5#67$78
5、保证不会出现非法的求值报文,例如类似这样字符串:
#4$5 //缺少操作数
4$5# //缺少操作数
4#$5 //缺少操作数
4 $5 //有空格
3+4-56/7 //有其它操作符
12345678987654321$54321 //32位整数计算溢出
输出描述:
根据输入的火星人字符串输出计算结果(结尾不带回车换行)
示例1
输入
7#6$5#12
输出
226
说明
示例:
7#6$5#12
=7#(18+5+2)#12
=7#25#12
=(14+75+4)#12
=93#12
=293+312+4
=226
public class ZT24 {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
String input = sc.nextLine();
while (input.contains("$") || input.contains("#")){
if (input.contains("$")) {//字符串左取右不取 7#6$5#12
int idx = input.lastIndexOf("$");
int leftStart = changeInput(input, idx, -1);
int op1 = Integer.parseInt(input.substring(leftStart,idx));
int rightEnd = changeInput(input, idx, +1);
int op2 = Integer.parseInt(input.substring(idx +1,rightEnd));
int res = calcStar('$', op1, op2);
input = input.substring(0,leftStart) + res + input.substring(rightEnd);
}else {
if (input.contains("#")) {
int idx = input.indexOf("#",0);
int leftStart = changeInput(input, idx, -1);
int op1 = Integer.parseInt(input.substring(leftStart,idx));
int rightEnd = changeInput(input, idx, +1);
int op2 = Integer.parseInt(input.substring(idx +1,rightEnd));
int res = calcStar('#', op1, op2);
input = input.substring(0,leftStart) + res + input.substring(rightEnd);
}
}
}
System.out.println(input);
}
//opt -1表示左边的整数 1表示右边的整数 7#6$5#12 leftStart rightEnd
private static int changeInput(String input,int idx,int opt){
char ch = input.charAt(idx + opt);
while (ch >= '0' && ch<= '9'){
if (opt>0){
opt++;
}else {
opt--;
}
if (idx + opt >=0 && idx + opt < input.length()){
ch = input.charAt(idx + opt);
}else {
break;
}
}
if (opt<0){
return opt + idx +1;
}else {
return opt + idx;
}
}
private static int calcStar(char ch, int op1,int op2){
if (ch == '#'){
return op1 * 2 + op2 * 3 + 4;
}else {
return 3 * op1 + op2 + 2;
}
}
}
025 【计算面积】
绘图机器的绘图笔初始位i在原点(0.0)。 机器启动后其绘图笔按下面规则绘制直线:
1 )尝试沿着横向坐标轴正向绘制直线,直到给定的终点值E,
2 )期间可通过指令在纵坐标轴方向进行偏移。井同时绘制直线,偏移后按规则1绘制直线;指令的格式为X offsetY。表示在横坐标X沿纵坐标方向偏移, offsetY为正数表示正向偏移,为负数表示负向偏移。
给定了横坐标终点值E.以及若干条绘制指令。请计算给制的直线和横坐标轴。以及X-E的直线组成图形的面积。
输入模述:
首行为两个整数NE。表示有N条指令。机器运行的横坐标終点值E.
接下来N行。每行两个整数表示-条给制指令x osorr。用例保证横坐标X以递增排序方式出现。且不会出现相同横坐标义。取值范围:0<N<= 10000, 0<X<= E<=20000, -10000<=offsetY<=10000.
输出描述:
一个整数,表示计算得到的面积。用例保证.结果范围在0-4294967295内
示例1:
输入
4 10
1 1
2 1
3 1
4 -2
输出
12
public class ZT25 {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
String[] input = sc.nextLine().split(" ");
int count = Integer.parseInt(input[0]);
int maxX1 = Integer.parseInt(input[1]);
int sqa = 0;
int tempX1 = 0;
int tempY1 = 0;
for (int i = 0; i < count; i++) {
String[] str = sc.nextLine().split(" ");
int x1New = Integer.parseInt(str[0]);
sqa += (x1New - tempX1) * Math.abs(tempY1);
tempY1 += Integer.parseInt(str[1]);
tempX1 = x1New;
}
sqa += (maxX1 - tempX1) * tempY1;
System.out.println(sqa);
}
}
026 【计算最大乘积】
给定一个元素类型为小写字符串的数组,请计算两个没有相同字符的元素 长度乘积的最大值,如果没有符合条件的两个元素,返回0。
输入描述:
输入为一个半角逗号分隔的小写字符串的数组,2 <= 数组长度<=100,0 < 字符串长度<= 50。
输出描述:
两个没有相同字符的元素 长度乘积的最大值。
示例1
输入
iwdvpbn,hk,iuop,iikd,kadgpf
输出
14
说明
数组中有5个元素。
iwdvpbn与hk无相同的字符,满足条件,iwdvpbn的长度为7,hk的长度为2,乘积为14(7*2)。
iwdvpbn与iuop、iikd、kadgpf均有相同的字符,不满足条件。
iuop与iikd、kadgpf均有相同的字符,不满足条件。
iikd与kadgpf有相同的字符,不满足条件。
因此,输出为14。
public class ZT26 {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
String[] split = sc.nextLine().split(",");
int max = 0;
for (int i = 0; i < split.length; i++) {
for (int j = i+1; j < split.length; j++) {
if (!checkHaveSame(split[i], split[j])){
max = Math.max(max,split[i].length() * split[j].length());
}
}
}
System.out.println(max);
}
private static boolean checkHaveSame(String str1,String str2){
//字符串排序
char[] chars1 = str1.toCharArray();
char[] chars2 = str2.toCharArray();
Arrays.sort(chars1);
Arrays.sort(chars2);
int idx1 = 0;
int idx2 = 0;
while (idx1<str1.length() && idx2< str2.length()){
if (chars1[idx1] == chars2[idx2]){
return true;
}else if (chars1[idx1] > chars2[idx2]){
idx2++;
}else if (chars1[idx1] < chars2[idx2]){
idx1++;
}
}
return false;
}
}
027 【检查是否存在满足条件的数字组合】
给定一个正整数数组,检查数组中是否存在满足规则的数字组合
规则:
A = B + 2C
输入描述:
第一行输入数组的元素个数。
接下来一行输入所有数组元素,用空格隔开。
输出描述:
如果存在满足要求的数,在同一行里依次输出规则里A/B/C的取值,用空格隔开。
如果不存在,输出0。
示例1:
输入
4
2 7 3 0
输出
7 3 2
说明
7 = 3 + 2 * 2
示例2:
输入
3
1 1 1
输出
0
说明
找不到满足条件的组合
备注:
数组长度在3-100之间。
数组成员为0-65535,数组成员可以重复,但每个成员只能在结果算式中使用一次。如:数组成员为[0, 0, 1, 5],0出现2次是允许的,但结果0 = 0 + 2 * 0是不允许的,因为算式中使用了3个0。
用例保证每组数字里最多只有一组符合要求的解。
public class ZT27 {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int count = Integer.parseInt(sc.nextLine());
int[] arr = new int[count];
String[] input = sc.nextLine().split(" ");
for (int i = 0; i < count; i++) {
arr[i] = Integer.parseInt(input[i]);
}
Arrays.sort(arr);
for (int i = 0; i < count; i++) {
for (int j = i + 1; j < count; j++) {
if (checkAdd(arr,i,j)) {
return;
}
}
}
System.out.println(0);
}
private static boolean checkAdd(int[] arr,int idx1,int idx2){//a
int sub1 = 2 * arr[idx1] + arr[idx2];
int sub2 = arr[idx1] + 2 * arr[idx2];
for (int i = 0; i < arr.length; i++) {
if (arr[i] == sub1 && i> idx1 && i> idx2) {
System.out.println(sub1 + " " + arr[idx2] + " " + arr[idx1]);
return true;
}
if (i> idx1 && i> idx2 && arr[i] == sub2) {
System.out.println(sub1 + " " + arr[idx1] + " " + arr[idx2]);
return true;
}
}
return false;
}
}
028 【矩阵扩散】
存在一个mn的二维数组,其成员取值范围为0或1。其中值为1的成员具备扩散性,每经过1S,将上下左右值为0的成员同化为1。二维数组的成员初始值都为0,将第[i,j]和[k,l]两个个位置上元素修改成1后,求矩阵的所有元素变为1需要多长时间。
输入描述:
输出数据中的前2个数字表示这是一个mn的矩阵,m和n不会超过1024大小;中间两个数字表示一个初始扩散点位置为i,j;最后2个数字表示另一个扩散点位置为k,l。
输出描述:
输出矩阵的所有元素变为1所需要秒数。
示例1:
输入
4,4,0,0,3,3
输出
3
说明
输出数据中的前2个数字表示这是一个4*4的矩阵;中间两个数字表示一个初始扩散点位置为0,0;最后2个数字表示另一个扩散点位置为3,3。
给出的样例是一个很简单模型,初始点在对角线上,达到中间的位置分别为3次迭代,即3秒。所以输出为3。
public class ZT28 {
private static int m1;
private static int n1;
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
String[] split = sc.nextLine().split(",");
m1 = Integer.parseInt(split[0]);
n1 = Integer.parseInt(split[1]);
int[][] arr = new int[m1][n1];
int x1 = Integer.parseInt(split[2]);
int y1 = Integer.parseInt(split[3]);
int x2 = Integer.parseInt(split[4]);
int y2 = Integer.parseInt(split[5]);
arr[x1][y1] = 1;
arr[x2][y2] = 1;
System.out.println(calcSecond(arr));
}
private static int calcSecond(int[][] arr){
int used = 0;
while (checkHasZero(arr)){
int[][] arrTemp = new int[m1][n1];
for (int i = 0; i < m1; i++) {
for (int j = 0; j < n1; j++) {
if (arr[i][j] == 1) {
arrTemp[i][j] = 1;
//上下左右
if (i-1 >= 0){
arrTemp[i-1][j] = 1;
}
if (i+1 < m1){
arrTemp[i+1][j] = 1;
}
if (j-1 >= 0){
arrTemp[i][j-1] = 1;
}
if (j+1 < n1){
arrTemp[i][j+1] = 1;
}
}
}
}
arr = arrTemp;
used++;
}
return used;
}
private static boolean checkHasZero(int[][] arr){
for (int i = 0; i < m1; i++) {
for (int j = 0; j < n1; j++) {
if (arr[i][j] == 0) {
return true;
}
}
}
return false;
}
}
029 【矩阵最大值】
给定一个仅包含0和1的N*N二维矩阵,请计算二维矩阵的最大值,计算规则如下:
1、 每行元素按下标顺序组成一个二进制数(下标越大越排在低位),二进制数的值就是该行的值。矩阵各行值之和为矩阵的值。
2、允许通过向左或向右整体循环移动每行元素来改变各元素在行中的位置。
比如: [1,0,1,1,1]向右整体循环移动2位变为[1,1,1,0,1],二进制数为11101,值为29。
[1,0,1,1,1]向左整体循环移动2位变为[1,1,1,1,0],二进制数为11110,值为30。
输入描述:
1、输入的第一行为正整数,记录了N的大小,0 < N <= 20。
2、输入的第2到N+1行为二维矩阵信息,行内元素边角逗号分隔。
输出描述:
矩阵的最大值。
示例1:
输入
5
1,0,0,0,1
0,0,0,1,1
0,1,0,1,0
1,0,0,1,1
1,0,1,0,1
输出
122
说明
第一行向右整体循环移动1位,得到本行的最大值[1,1,0,0,0],二进制值为11000,十进制值为24。
第二行向右整体循环移动2位,得到本行的最大值[1,1,0,0,0],二进制值为11000,十进制值为24。
第三行向左整体循环移动1位,得到本行的最大值[1,0,1,0,0],二进制值为10100,十进制值为20。
第四行向右整体循环移动2位,得到本行的最大值[1,1,1,0,0],二进制值为11100,十进制值为28。
第五行向右整体循环移动1位,得到本行的最大值[1,1,0,1,0],二进制值为11010,十进制值为26。
因此,矩阵的最大值为122。
public class ZT29 {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int num = Integer.parseInt(sc.nextLine());
//如何把1全部移动到高位0到低位
int total = 0;
for (int i = 0; i < num; i++) {
String[] split = sc.nextLine().split(",");
StringBuilder sb = new StringBuilder();
for (int j = 0; j < num; j++) {
sb.append(split[j]);
}
total += calcMax(sb.toString(), num);
}
System.out.println(total);
}
//最多移动num次
private static int calcMax(String str,int num){
int max = Integer.parseInt(str,2);
while (num>1){
String tem = str.substring(1) + str.charAt(0);
max = Math.max(max,Integer.parseInt(tem,2));
str = tem;
num--;
}
return max;
}
}
030 【考勤信息】
公司用一个字符串来表示员工的出勤信息:
absent:缺勤
late:迟到
leaveearly:早退
present:正常上班
现需根据员工出勤信息,判断本次是否能获得出勤奖,能获得出勤奖的条件如下:
缺勤不超过一次;没有连续的迟到/早退;任意连续7次考勤,缺勤/迟到/早退不超过3次
输入描述:
用户的考勤数据字符串,记录条数 >= 1;输入字符串长度<10000;不存在非法输入
如:
2
present
present absent present present leaveearly present absent
输出描述:
根据考勤数据字符串,如果能得到考勤奖,输出"true";否则输出"false",对于输入示例的结果应为:
true false
示例1:
输入
2
present
present present
输出
true true
示例2:
输入
2
present
present absent present present leaveearly present absent
输出
true false