华为机试23题总结

(声明:我没有全量用例,所以不保证全过,只能说给出样例输入可以跑过。不要指望我这是标准答案,这也是自己写的。要标准答案的自己写去。)

目录

第一题 勾股元组数

第二题  整数对最小和

第三题  n 阶方阵和

第四题  TLV解码

第五题  猴子跳台阶 1级和3级(递归的循环写法)

第六题  GPU 算力

第七题  身高排序(绝对差值)【考察 list.sort(new Comparator<>(){})】

第八题  区间字符串倒转输出

第九题  购买最多商品【穷举法,TreeSet 排序】

第十题  字符串排序

第十一题 int 字节和(位运算)

第十二题  无题目,好像是迷宫

第十三题 二叉树存储数组

第十四题  装最多快递

第十五题  航天器太阳能板,无图看不懂

第十六题  单词接龙  后一个字符串前缀是前一个字符串后缀

第十七题  第 k 长子串

第十八题  喊7

第十九题  删除出现次数最少字符串

第二十题  走到最后一个成员最小步数

第二十一题(同二十题)

第二十二题  轮流合并新数组

第二十三题  磁盘容量排序


第一题 勾股元组数

//        如果三个正整数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
         输出
          abc

          2
          输入
          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;
    }

}

  • 16
    点赞
  • 230
    收藏
    觉得还不错? 一键收藏
  • 8
    评论
### 回答1: 太阳能板的最大面积和Java编程没有直接的关系。太阳能板的面积是根据实际需和技术限制来确定的。 太阳能板是一种将太阳能光转化为电能的装置,通常由许多太阳能电池组成。太阳能电池是一种半导体材料,当太阳光照射到其表面时,会产生电流。太阳能板的面积越大,就可以吸收更多的太阳能,从而产生更多的电能。 太阳能板的面积可以根据实际的需来确定。例如,如果用于家庭用途,可以根据家庭的用电量和可安装的空间来确定太阳能板的大小。如果用于工业或商业用途,可以根据能源需和可用空间来决定太阳能板的面积。 至于Java编程,在太阳能板的制造和控制过程中可能会涉及到。比如,对于太阳能板生产线的控制,可以使用Java编程语言来编写相关的控制程序。此外,太阳能监测系统也可以通过Java编程来实现数据的获取、处理和分析。 总之,太阳能板的最大面积并没有直接关联到Java编程,它需要根据实际需和技术限制来确定。然而,在太阳能板的生产和控制过程中,Java编程可能会起到一定的作用。 ### 回答2: 太阳能板的最大面积主要取决于太阳能板的设计和制造技术,以及太阳能资源的丰富程度。在目前的技术水平下,太阳能板的最大面积一般受到以下几个因素的限制: 1. 材料和结构:太阳能板通常采用硅基薄膜或多晶硅等材料制成,而这些材料本身对太阳能的吸收和转化能力有一定的限制。另外,太阳能板的结构设计(如光伏电池的排列方式)也会影响其最大面积。 2. 太阳能资源:太阳能的光照强度和持续时间是影响太阳能板发电效率的重要因素。在日照条件良好和光照时间较长的地区,太阳能板的最大面积往往可以更大。 3. 建筑空间限制:太阳能板通常需要安装在建筑物的屋顶或太阳能架上,而建筑物的实际能容纳的面积会对太阳能板的最大面积产生影响。此外,有些地区的建筑规定也会对太阳能板的安装面积做出限制。 总的来说,目前太阳能板的最大面积一般在几十平方米至几百平方米之间,具体取决于上述因素。随着科技的不断进步和太阳能技术的发展,太阳能板的最大面积可能会有所增加,这也将有助于提高太阳能利用的效率和推广应用。 ### 回答3: 太阳能板的最大面积取决于多个因素,包括太阳能辐射强度、安装位置、形状和材质等。在理想的条件下,太阳能板的最大面积是指在可获得最大太阳辐射的情况下,太阳能板可以有效吸收并转换为电能的面积。 太阳能辐射强度是影响太阳能板最大面积的重要因素之一。较高的太阳能辐射意味着太阳能板可以获得更多的能量,从而可以安装更大的面积。一般来说,接近赤道的地区太阳辐射较强,因此在这些地方可以安装更大尺寸的太阳能板。 安装位置也会影响太阳能板的最大面积。太阳能板应该根据可用的空间进行布置,使其面向太阳并获得最大的阳光照射。在平坦的屋顶或者稳定的地面上,可以安装较大面积的太阳能板。而在有限的空间,例如窄小的屋顶或者城市建筑物上,太阳能板的尺寸可能会受限。 太阳能板的形状和材质也会对其最大面积产生影响。不同的形状和材质对太阳能的吸收和转换效率有所差异。一般来说,方形或长方形的太阳能板可以安装更大面积,而圆形或异形太阳能板面积较小。 总的来说,在当前技术水平下,太阳能板最大面积一般在一定范围内,需要根据具体条件和需来设计和选择。随着太阳能技术的发展和创新,未来可能会有更大面积的太阳能板问世。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 8
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值