admin管理员组文章数量:1516870
华为OD机试(1
华为OD机试算法题新老题库练习及源码
- 老题库
- 1.敏感字段加密
- 2.IPv4地址转换成整数
- 3.VLAN资源池
- 4. 求字符串中所有整数的最小和
- 5.求满足条件的最长子串的长度
- 6.字符串分割
- 7.一种字符串压缩表示的解压
- 8.矩阵最大值
- 9.单词接龙
- 10.找出符合要求的字符串子串
- 11.字符串加密
- 12.英文输入法
- 13.按索引范围翻转文章片段
- 14. TLV解析Ⅰ
- 15.字符串筛选排序
- 16.连续字母长度
- 17.拼接URL
- 18.非严格递增连续数字序列
- 19.相对开音节
- 20.最远足迹
郑重声明: 1.博客中涉及题目为网上搜索而来,若侵权,请联系作者删除。 源码内容为个人原创,仅允许个人学习使用。
2.博客中涉及的源码非官方答案,不保证正确性。
3.切勿将博客内容用于官方考试,若应用于官方考试,后果自行承担,与原作者无关。
4.原作者保留知识版权,且有权向侵权者追究刑事责任
老题库
1.敏感字段加密
给定一个由多个命令字组成的命令字符串:
1、字符串长度小于等于127字节,只包含大小写字母,数字,下划线和偶数个双引号
2、命令字之间以一个或多个下划线 _ 进行分割;
3、可以通过两个双引号”来标识包含下划线 的命令字或空命令字(仅包含两个双引号的命令字),双引号不会在命令字内部出现
请对指定索引的敏感字段进行加密,替换为****** (6个*) ,并删除命令字前后多余的下划线如果无法找到指定索引的命令字,输出字符串ERROR。
输入描述
输入为两行,第一行为命令字索引K (从0开始) ,第二行为命令字符串S.
输出描述
输出处理后的命令字符串,如果无法找到指定索引的命令字,输出字符串ERROR
| 输入1 | 输入2 | 输出 | 说明 |
|---|---|---|---|
| 1 | password__a12345678_timeout_100 | password_******_timeout_100 | 加密第二个命令字 |
| 2 | aaa_password_“a12_45678”timeout__100_“”_ | aaa_password_******_ timeout__“” | 加密第三个命令字 |
源码和解析
解析:
1.将输入的命令字串转换成单字符数组 char[]
2.遍历单字符数组,并判断单个字符的含义
2.1 遍历字符数组,遇到指令截止符,则代表一个命令字结束,截止符有以下几种情况
2.1.1 第二次双引号出现
2.1.2 下划线(需要判断是否前面有引号,若有,则代表不是截止符。空下划线过滤掉)
2.1.3 字符数组遍历结束时 即最后一个字符
2.2 不断产生命令字后加入List之中
2.3 判断输入的索引是否越界
2.3.1 若越界 则输出ERROR
2.3.2 若未越界 将索引对应位置的命令字替换为*****
2.4 遍历List 产生最后的加密指令
示例代码:
import java.util.*;
import java.util.Scanner;
public class T1 {static Scanner scanner=new Scanner(System.in);public static void main(String[] args) {System.out.println("请输入索引:");int index=Integer.parseInt(scanner.nextLine());System.out.println("请输入命令串:");String input=scanner.nextLine();char[] chArr=input.toCharArray();String cmd="";List<String> cmdList=new ArrayList<>();for(int i=0;i<chArr.length;i++){char item=chArr[i];if(item=='"'&&cmd.contains(item+"")){//如果是双引号 且该命令字内有 那么就是结束的双引号cmd+="\"";cmdList.add(cmd);cmd="";}else if(item=='_'&&!cmd.contains("\"")){//item=='_' 下划线 表示指令结束//!cmd.contains("\"") 该命令内前面不包含" 若包含 则是引号内的 为同一个命令字//cmd.equals("") 该命令字内是空的 那么就是空下划线 无意义 过滤掉if(!cmd.equals("")){cmdList.add(cmd);cmd="";}}else if(i==chArr.length-1){//如果是最后一位 则直接结束最后一个命令字cmd+=item;cmdList.add(cmd);cmd="";}else{//其他 情况 则是命令字cmd+=item;}}//password__a12345678_timeout_100//aaa_password_"a12_45678"_timeout__100_""_if(index>cmdList.size()-1||index<0){System.out.println("ERROR");}else{cmdList.set(index, "******");String result="";for(String item:cmdList){result+="_"+item;}result=result.replaceFirst("_", "");System.out.println(result);}}
}
若需要提高效率,则可以考虑使用StringBuilder或StringBuffer来完成。而不是直接使用String字符串进行拼接。
String 是 Java 中基础且重要的类,被声明为 final class,是不可变字符串。因为它的不可变性,所以拼接字符串时候会产生很多无用的中间对象,如果频繁的进行这样的操作对性能有所影响。
StringBuffer 就是为了解决大量拼接字符串时产生很多中间对象问题而提供的一个类。它提供了 append 和 add 方法,可以将字符串添加到已有序列的末尾或指定位置,它的本质是一个线程安全的可修改的字符序列。
在很多情况下我们的字符串拼接操作不需要线程安全,所以 StringBuilder 登场了。StringBuilder 是 JDK1.5 发布的,它和 StringBuffer 本质上没什么区别,就是去掉了保证线程安全的那部分,减少了开销。
线程安全:
StringBuffer:线程安全
StringBuilder:线程不安全
速度:
一般情况下,速度从快到慢为 StringBuilder > StringBuffer > String,当然这是相对的,不是绝对的。
使用环境:
操作少量的数据使用 String。
单线程操作大量数据使用 StringBuilder。
多线程操作大量数据使用 StringBuffer。
2.IPv4地址转换成整数
题目描述
存在一种虚拟IPv4地址,由4小节组成,每节的范围为0-255,以#号间隔,虚拟IPv4地址可以转换为一个32位的整数,例如:128#0#255#255,转换为32位整数的结果为2147549183(0x8000FFFF)1#0#0#0,转换为32位整数的结果为16777216(0x01000000)。
现以字符串形式给出一个虚拟IPv4地址,限制第1小节的范围为1-128,即每一节范围分别为
(1-128)#(0-255)#(0-255)#(0-255)
要求每个IPv4地址只能对应到唯一的整数上。如果是非法IPv4,返回invalid IP
输入描述
输入一行,虚拟IPv4地址格式字符串
输出描述
输出一行,按照要求输出整型或者特定字符
| 输入 | 输出 | 说明 |
|---|---|---|
| 100#101#1#5 | 1684340997 | 无 |
| 1#2#3 | invalid IP | 无 |
源码和解析
解析:
1.字符串按#号拆分 若分为四段 且每段数字都在范围内 ,那么ip合规 。否则输出invalid IP
2.将每段ip转成16进制,注意转换后每段2位,拼接为16进制字符串 最后再输出16进制对应的10进制即可
注意:Integer.parseInt()方法转换时最大值为 2147483647 范围不够 因此使用时使用Long.parseLong()方法进行进制转换
128#0#255#255,转换为32位整数的结果为2147549183>2147483647
示例代码:
public class T2 {public static void main(String[] args) {String input="128#168#100#5";String[] ipArr=input.split("#");//长度校验if(ipArr.length!=4){System.out.println("invalid IP");System.exit(0);}// 数字范围校验if(1>Integer.parseInt(ipArr[0])||Integer.parseInt(ipArr[0])>128){System.out.println("invalid IP");System.exit(0);}for(int i=1;i<4;i++){if(0>Integer.parseInt(ipArr[i])||Integer.parseInt(ipArr[i])>255){System.out.println("invalid IP");System.exit(0);}}//10进制转换为16进制String oxStr="";for(int i=0;i<4;i++){ipArr[i]=Integer.toString(Integer.parseInt(ipArr[i]),16);if(ipArr[i].length()==1){ipArr[i]="0"+ipArr[i];}oxStr+=ipArr[i];}//System.out.println(oxStr);//16进制转换为10进制System.out.println(Long.parseLong(oxStr, 16));}
}
3.VLAN资源池
题目描述
VLAN是一种对局域网设备进行逻辑划分的技术,为了标识不同的VLAN,引入VLAN ID(1-4094之间的整数)的概念。
定义一个VLAN ID的资源池(下称VLAN资源池),资源池中连续的VLAN用开始VLAN-结束VLAN表示,不连续的用单个整数表示,所有的VLAN用英文逗号连接起来。
现在有一个VLAN资源池,业务需要从资源池中申请一个VLAN,需要你输出从VLAN资源池中移除申请的VLAN后的资源池。
输入描述
第一行为字符串格式的VLAN资源池,第二行为业务要申请的VLAN,VLAN的取值范围为[1,4094]之间的整数。
输出描述
从输入VLAN资源池中移除申请的VLAN后字符串格式的VLAN资源池,输出要求满足题目描述中的格式,并且按照VLAN从小到大升序输出。
如果申请的VLAN不在原VLAN资源池内,输出原VLAN资源池升序排序后的字符串即可。
| 输入1 | 输入2 | 输出 | 说明 |
|---|---|---|---|
| 1-5 | 2 | 1,3-5 | 原VLAN资源池中有VLAN 1、2、3、4、5,从资源池中移除2后,剩下VLAN 1、3、4、5,按照题目描述格式并升序后的结果为1,3-5。 |
| 20-21,15,18,30,5-10 | 15 | 5-10,18,20-21,30 | 原VLAN资源池中有VLAN 5、6、7、8、9、10、15、18、20、21、30,从资源池中移除15后,资源池中剩下的VLAN为 5、6、7、8、9、10、18、20、21、30,按照题目描述格式并升序后的结果为5-10,18,20-21,30。 |
| 5,1-3 | 10 | 1-3,5 | 原VLAN资源池中有VLAN 1、2、3,5,申请的VLAN 10不在原资源池中,将原资源池按照题目描述格式并按升序排序后输出的结果为1-3,5。 |
源码和解析
解析:
可以将输入的资源池 转换为数组 例如1,3-5=> [1,3,4,5] 移除目标资源3后再重新合并为 [1,4-5]
示例代码:
import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;public class T3 {public static void main(String[] args) {//输入的VLAN串 20-21,15,18,30,5-10 String input="20-21,15,18,30,5-10";//要申请的VLAN资源Integer destVlan=15;//获得VLAN池List<Integer> vlanPool=new ArrayList<Integer>();//VLAN池String[] vlanGroup=input.split(",");for(int i=0;i<vlanGroup.length;i++){if(vlanGroup[i].contains("-")){String vlanItems[]=vlanGroup[i].split("-");Integer start=Integer.parseInt(vlanItems[0]);Integer end=Integer.parseInt(vlanItems[1]);for(int j=start;j<=end;j++){vlanPool.add(j);}continue;}vlanPool.add(Integer.parseInt(vlanGroup[i]));}//升序排序vlanPool.sort(new Comparator<Integer>() {@Overridepublic int compare(Integer o1, Integer o2) {if(o1>o2){return 1;}if(o1<o2){return -1;}return 0;}});//移出要移出的那个数vlanPool.remove(destVlan);//注意目标vlan要保持和List的值相同String result="";Integer last=null;//记录追加的最后一个值for(int index=0;index<vlanPool.size();index++){if(last==null){result+=vlanPool.get(index);last=vlanPool.get(index);continue;}if(vlanPool.get(index)-last==1){if(result.endsWith("-"+last)){//已经有一个结束的数字了 那么就替换掉这个result=result.replace(last+"", vlanPool.get(index)+"");}else{result+="-"+vlanPool.get(index);}}else{result+=","+vlanPool.get(index);}last=vlanPool.get(index);}System.out.println(vlanPool);System.out.println(result);}
}
4. 求字符串中所有整数的最小和
题目描述
输入字符串s,输出s中包含所有整数的最小和。
说明:
字符串s,只包含 a-z A-Z ± ;合法的整数包括
1) 正整数 一个或者多个0-9组成,如 0 2 3 002 102
2) 负整数 负号 – 开头,数字部分由一个或者多个0-9组成,如 -0 -012 -23 -00023
输入描述
包含数字的字符串
输出描述
所有整数的最小和
| 输入 | 输出 | 说明 |
|---|---|---|
| bb1234aa | 10 | 1+2+3+3=10 |
| b12-34aa | -31 | 1+2+(-34) = -31 |
源码和解析
解析:
若字符串全是整数,那么直接逐个抽离出数字相加即可
若字符串包含负数,那么需要尽可能让负数(绝对值最大)最小
注意字符中对减号的处理
示例代码:
import java.util.ArrayList;
import java.util.List;public class T4 {public static void main(String[] args) {String input="b12-34aA1C79-3A";//转换成单字符数组char[] singleCases=input.toCharArray();List<Integer> numberList=new ArrayList<Integer>();boolean flag=false;String negNumer="-"; //记录负数for(char sc:singleCases){if( (sc>='a'&&sc<='z') || (sc>='A'&&sc<='Z') || (sc=='+')){//是字符 给过滤掉 字符会截断负数 让负数达不到最小flag=false;if(!negNumer.equals("-")){numberList.add(Integer.parseInt(negNumer));}negNumer="-";continue;}if(sc=='-'){flag=true;negNumer="-";continue;}if(flag==true){negNumer+=sc;continue;}else{numberList.add(Integer.parseInt(sc+""));}}//求和Integer sum=0;for(Integer item:numberList){sum+=item;}System.out.println(numberList);System.out.println("最小和为:"+sum);}
}
5.求满足条件的最长子串的长度
题目描述
给定一个字符串,只包含字母和数字,按要求找出字符串中的最长(连续)子串的长度,字符串本身是其最长的子串,子串要求:
1、 只包含1个字母(a-z, A-Z),其余必须是数字;
2、 字母可以在子串中的任意位置;
如果找不到满足要求的子串,如全是字母或全是数字,则返回-1。
输入描述
字符串(只包含字母和数字)
输出描述
子串的长度
| 输入 | 输出 | 说明 |
|---|---|---|
| abC124ACb | 4 | 满足条件的最长子串是C124或者124A,长度都是4 |
| a5 | 2 | 无 |
| aBB9 | 2 | 满足条件的为B9,长度为2 |
| abcdef | -1 | 没有满足条件的子串 |
源码和解析
解析:
将输入字符转换成单字符数组,遍历数组拿到满足条件的子串。将子串装入List,最后拿到最长子串的长度
子串开始字符是字母,下一个字母就是子串结束的标识,且不包含
子串开始字符是数字,字母出现就是子串结束的标识,要包含
所以一个子串结束时可以以字母来判断。若最后一位不是字符,是数字时不要遗漏。
示例代码:
import java.util.ArrayList;
import java.util.List;public class T5 {public static void main(String[] args) {String input="abC124ACb";char singleCases[]=input.toCharArray();boolean isCaseStart=false;//是字符开头?StringBuilder strItem=new StringBuilder();//定义一个子串List<String> strList=new ArrayList<String>();//所有满足条件的子串都装进来for(int i=0;i<singleCases.length;i++){char sc=singleCases[i];//开始字符的处理if(strItem.length()==0&&isCase(sc)){//子串是空 且当前字符为字母isCaseStart=true;strItem.append(sc);continue;}else if(strItem.length()==0&&!isCase(sc)){//子串是空 但是当前不是字符isCaseStart=false;strItem.append(sc);continue;}//后续字符判断if(isCaseStart==true&&isCase(sc)){//字母开头, 且当前字符是字母 意味着一个子串结束if(strItem.length()>=2){//至少包含了一个数字strList.add(strItem.toString());}strItem.setLength(0);//清空strItem.append(sc);//追加新的字母 期待下一次连续continue;}if(isCaseStart==false &&isCase(sc)){//非字母开头,且当前字符是字母 意味着一个子串结束 当字符需要保留strItem.append(sc);if(strItem.length()>=2){strList.add(strItem.toString());}isCaseStart=true;//这回字符开头了strItem.setLength(0);//清空strItem.append(sc);//追加新的字母 期待下一次连续continue;}strItem.append(sc);//最后一位是数字时 必须首字符是字母if(i==singleCases.length-1&&isCaseStart){if(strItem.length()>=2){strList.add(strItem.toString());}}}int max=-1;for(String item:strList){if(item.length()>max){max=item.length();}}System.out.println("满足条件最大子串:"+max);}public static boolean isCase(char item){return (item<='z'&&item>='a') ||(item<='Z'&&item>='A');}
}
6.字符串分割
题目描述
给定一个非空字符串S,其被N个‘-’分隔成N+1的子串,给定正整数K,要求除第一个子串外,其余的子串每K个字符组成新的子串,并用‘-’分隔。
对于新组成的每一个子串,如果它含有的小写字母比大写字母多,则将这个子串的所有大写字母转换为小写字母;
反之,如果它含有的大写字母比小写字母多,则将这个子串的所有小写字母转换为大写字母;大小写字母的数量相等时,不做转换。
输入描述
输入为两行,第一行为参数K,第二行为字符串S。
输出描述
输出转换后的字符串
| 输入1 | 输入2 | 输出 | 说明 |
|---|---|---|---|
| 3 | 12abc-abCABc-4aB@ | 12abc-abc-ABC-4aB-@ | |
| 12 | 12abc-abCABc-4aB@ | 12abc-abCABc4aB@ |
源码和解析
解析:
依据题意 第一个子串不做变化,可以另外保存
将第一个子串外的其他子串合并为为一个字符串,再根据长度拆分为新的子串
判断新的子串中字符的大小写情况来来做大小写变化
示例代码:
import java.util.ArrayList;
import java.util.List;public class T6 {public static void main(String[] args) {int number = 6;// 拆分数String input = "12abc-abCABc-4aB@a"; // 输入的子串String[] strArr = input.split("-");String tempStr = "";// 临时子串for (int i = 1; i < strArr.length; i++) {tempStr += strArr[i];// 产生新的子串}// 按拆分数重新分配子串List<String> strList = new ArrayList<String>();strList.add(strArr[0]);System.out.println(tempStr);if (tempStr.length() < number) {strList.add(tempStr);} else {while (tempStr.length() > 0) {if (tempStr.length() >= number) {String item = tempStr.substring(0, number);strList.add(item);tempStr = tempStr.replaceFirst(item, "");} else {if (tempStr.length() > 0) {strList.add(tempStr);tempStr = "";}}}}// 针对每个子串进行大小写判断 并产生新的子串String result = strArr[0];for (String item : strList) {if (!item.equals(strArr[0])) {// 开始判断result += "-" + trans(item);}}// System.out.println(strList);System.out.println(result);}// 字符串的变化处理static String trans(String key) {int bigNumber = 0;int littleNumber = 0;char chArr[] = key.toCharArray();for (char c : chArr) {if (c >= 'a' && c <= 'z')littleNumber++;if (c >= 'A' && c <= 'Z')bigNumber++;}if (bigNumber > littleNumber) {key = key.toUpperCase();} else if (bigNumber < littleNumber) {key = key.toLowerCase();}return key;}
}
7.一种字符串压缩表示的解压
题目描述
有一种简易压缩算法:针对全部由小写英文字母组成的字符串,将其中连续超过两个相同字母的部分压缩为连续个数加该字母,其他部分保持原样不变。
例如:字符串“aaabbccccd”经过压缩成为字符串“3abb4cd”。
请您编写解压函数,根据输入的字符串,判断其是否为合法压缩过的字符串,
若输入合法则输出解压缩后的字符串,否则输出字符串“!error” 来报告错误
输入描述
输入一行,为一个ASCII字符串,长度不会超过100字符,用例保证输出的字符串长度也不会超过100字符。
输出描述
若判断输入为合法的经过压缩后的字符串,则输出压缩前的字符串;若输入不合法,则输出字符串“
| 输入 | 输出 | 说明 |
|---|---|---|
| 4dff | ddddff | 4d扩展为dddd,故解压后的字符串为ddddff。 |
| 2dff | !error | 两个d不需要压缩,故输入不合法。 |
| 4d@A | !error | 全部由小写英文字母组成的字符串压缩后不会出现特殊字符@和大写字母A,故输入不合法。 |
源码和解析
解析:
按照题意可知:
1.合法的压缩字串只应包含数字和小写字母 包含其他字符则为不合法的,且数字必须大于2,否则也是不合法的。例如dd压缩为2d 其字符数并未减少,达不到压缩的效果。数字后必须出现字符,否则也是不合法的数据。最后一位是数字也不行
2.解决这个题,首先得判读是否合法,若合法,则再进行还原
3.还原时遇见数字n,则可以使用循环,来产生n个数字后出现的字符。
import java.util.ArrayList;public class T7 {public static void main(String[] args) {String input = "4dff";if (!check(input)) {System.out.println("!error");System.exit(0);}char chArr[] = input.toCharArray();// 重组字符 a15dff3d=> [1,15,d,f,f,3,d]ArrayList<String> chList = new ArrayList<>();String item = "";boolean isNumber = false;StringBuilder result = new StringBuilder();for (char c : chArr) {if (isNumberic(c)) {// 当前是数字if (isNumber) {// 前一个字符也是数字item += c;} else {// 前一个字符不是数字item = c + "";isNumber = true;}} else {// 是字符if (isNumber) {// 前面的是数字chList.add(item);item = "";isNumber = false;}chList.add(c + "");}}boolean flag = false;// 前一位是否是数字for (int j = 0; j < chList.size(); j++) {String n = chList.get(j);if (n.length() == 1) {// 单字符 可能是数字 也可能是字母if (isNumberic(n.charAt(0))) {// 是数字int len = Integer.parseInt(n);if (len <= 2) {System.out.println("!error");System.exit(0);}for (int i = 0; i < len; i++) {result.append(chList.get(j + 1));}flag = true;} else {// 是字符if (flag == false) {// 前一位是字符 直接拼接result.append(n);}flag = false;}} else {// 肯定是数字int len = Integer.parseInt(n);flag = true;for (int i = 0; i < len; i++) {result.append(chList.get(j + 1));}}}// System.out.println(chList);System.out.println(result);}// 判断单字符是否是数字static boolean isNumberic(char c) {int chr = c;// 转为ASCII码来判断 48位0if (chr >= 48 && chr <= 57) { // (int)'0' ==>48return true;}return false;}// 检查只包含数字和小写字母(未来过滤2及以下数字)static boolean check(String param) {char chArr[] = param.toCharArray();// 最后一位是数字也不行if (isNumberic(chArr[chArr.length - 1])) {return false;}boolean flag = true;for (char c : chArr) {if (c >= 'a' && c <= 'z') {continue;}int chr = c;// 转为ASCII码来判断 48位0if (chr >= 48 && chr <= 57) { // (int)'0' ==>48continue;}flag = false;break;}return flag;}
}
8.矩阵最大值
题目描述
给定一个仅包含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行为二维矩阵信息,行内元素边角逗号分隔。
输出描述
矩阵的最大值
| 输入 | 输出 | 说明 |
|---|---|---|
| 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。 |
源码和解析
解析:
对每行的数据进行n次右移,就可以得到最大的可能。求出每行的最大值即可
示例代码:
public class T8 {public static void main(String[] args) {int number = 5;int[][] numArr = { { 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 } };// number = 3;// int[][] numArr ={{1,0,1},{0,1,0},{0,0,1}};int sum = 0;// 最后的和for (int[] arr : numArr) {int[] tmpArr = arr;int max = 0;for (int i = 0; i < arr.length; i++) {tmpArr = toRight(tmpArr, number);String binStr = "";for (int j = 0; j < tmpArr.length; j++) {// System.out.print(tmpArr[j] + ",");binStr += tmpArr[j];}int num = Integer.parseUnsignedInt(binStr, 2);if (max < num) {max = num;}System.out.println("单行最值:" + max);}sum += max;// 每行的最大值相加System.out.println("_________");}System.out.println("矩阵的最大值为:" + sum);}public static int[] toRight(int[] arr, int n) {// 右移一位int tempArr[] = arr.clone();for (int i = 1; i < arr.length - 1; i++) {tempArr[i] = arr[i - 1];}tempArr[0] = arr[arr.length - 1];tempArr[arr.length - 1] = arr[arr.length - 2];return tempArr;}
}
9.单词接龙
题目描述
单词接龙的规则是:
可用于接龙的单词首字母必须要与前一个单词的尾字母相同;
当存在多个首字母相同的单词时,取长度最长的单词,如果长度也相等,则取字典序最小的单词;已经参与接龙的单词不能重复使用。
现给定一组全部由小写字母组成单词数组,并指定其中的一个单词作为起始单词,进行单词接龙,
请输出最长的单词串,单词串是单词拼接而成,中间没有空格。
输入描述
输入的第一行为一个非负整数,表示起始单词在数组中的索引K,0 <= K < N ;
输入的第二行为一个非负整数,表示单词的个数N;
接下来的N行,分别表示单词数组中的单词。
备注:
单词个数N的取值范围为[1, 20];
单个单词的长度的取值范围为[1, 30];
输出描述
输出一个字符串,表示最终拼接的单词串。
| 输入 | 输出 | 说明 |
|---|---|---|
| 0 6 word dd da dc dword d | worddwordda | 先确定起始单词word,再接以d开头的且长度最长的单词dword,剩余以d开头且长度最长的有dd、da、dc,则取字典序最小的da,所以最后输出worddwordda。 |
| 4 6 word dd da dc dword d | dwordda | 先确定起始单词dword,剩余以d开头且长度最长的有dd、da、dc,则取字典序最小的da,所以最后输出dwordda。 |
源码和解析
解析:
将输入字符装入列表之中,取出索引对应位置的内容,并将其从列表之中移出
遍历集合,类似于找最值的方式 找出最优的那个字符进行接龙,接龙后将字符从列表移出
接龙后产生新的目标串和后缀,再从列表中进行查找最优子串接龙
直到找不到接龙的子串为止
import java.util.ArrayList;
import java.util.Scanner;public class T9 {public static void main(String[] args) {System.out.println("请输入开始索引:");Scanner scanner = new Scanner(System.in);int startIndex = Integer.parseInt(scanner.nextLine());System.out.println("请输入单词数:");int number = Integer.parseInt(scanner.nextLine());ArrayList<String> strList = new ArrayList<>();for (int i = 0; i < number; i++) {strList.add(scanner.nextLine());}String result = strList.get(startIndex);strList.remove(startIndex);// 移出第一个String rString = getDrog(strList, result.charAt(result.length() - 1));while (rString != null) {result += rString;strList.remove(rString);rString = getDrog(strList, result.charAt(result.length() - 1));}System.out.println(result);// System.out.println(strList);}public static String getDrog(ArrayList<String> strList, char suffix) {ArrayList<String> tempList = new ArrayList<>();for (String item : strList) {if (item.startsWith(suffix + "")) {tempList.add(item);}}String objStr = "";int maxLength = 0;// 最大长度if (tempList.size() == 0) {return null;}for (String item : tempList) {if (item.length() > maxLength) {maxLength = item.length();objStr = item;continue;}if (item.length() == maxLength) {if (objStrpareTo(item) > 0) {objStr = item;// 修改了}}}return objStr.equals("") ? null : objStr;}
}
10.找出符合要求的字符串子串
题目描述
给定两个字符串,从字符串2中找出字符串1中的所有字符,去重并按照ASCII值从小到大排序。
输入字符串1:长度不超过1024
输入字符串2:长度不超过1000000\n\n字符范围满足ASCII编码要求,按照ASCII的值由小到大排序
输入描述
bach
bbaaccedfg
输出描述
abc
输入字符串1 为给定字符串bach,输入字符串2 bbaaccedfg
从字符串2中找出字符串1的字符,去除重复的字符,并且按照ASCII值从小到大排序,得到输出的结果为abc。
字符串1中的字符h在字符串2中找不到不输出。
| 输入1 | 输入2 | 输出 | 说明 |
|---|---|---|---|
| fach | bbaaccedfg | acf | 无 |
源码和解析
解析:
去除重复字符 可以使用set集合
如果字符串2中 包含字符串1中的单个字符,那么那个字符就是目标字符。其他字符则不需保留
import java.util.ArrayList;
import java.util.Comparator;
import java.util.HashSet;
import java.util.List;
import java.util.Set;public class T10 {public static void main(String[] args) {String input1 = "fach";String input2 = "bbaaccedfg";Set<Character> characters = new HashSet<>();for (char c : input1.toCharArray()) {characters.add(c);};Set<Character> characters2 = new HashSet<>();for (char c : input2.toCharArray()) {characters2.add(c);};// 求两个集合的交集List<Character> cList = new ArrayList<Character>();for (char c : characters) {// 不包含的就移出掉if (characters2.contains(c)) {cList.add(c);}}cList.sort(new Comparator<Character>() {@Overridepublic int compare(Character o1, Character o2) {if (o1 < o2)return -1;if (o1 > o2)return 1;return 0;}});for (Character c : cList) {System.out.print(c);}}
}
11.字符串加密
题目描述
给你一串未加密的字符串str,通过对字符串的每一个字母进行改变来实现加密,加密方式是在每一个字母str[i]偏移特定数组元素a[i]的量,数组a前三位已经赋值:a[0]=1,a[1]=2,a[2]=4。
当i>=3时,数组元素a[i]=a[i-1]+a[i-2]+a[i-3]。
例如:原文 abcde 加密后 bdgkr,其中偏移量分别是1,2,4,7,13。
输入描述
第一行为一个整数n(1<=n<=1000),表示有n组测试数据,每组数据包含一行,原文str(只含有小写字母,0<长度<=50)。
输出描述
每组测试数据输出一行,表示字符串的密文。
| 输入 | 输出 | 说明 |
|---|---|---|
| 1 xy | ya | 第一个字符x偏移量是1,即为y,第二个字符y偏移量是2,即为a。 |
源码和解析
解析:
字符加密后会产生偏移。这种其实是最简单的加密,只需要通过ASCII码进行转换即可
import java.util.ArrayList;
import java.util.Scanner;public class T11 {public static void main(String[] args) {Scanner scanner = new Scanner(System.in);System.out.println("请输入测试字符数:");int number = Integer.parseInt(scanner.nextLine());ArrayList<String> strList = new ArrayList<>();ArrayList<Integer> pianYiList = new ArrayList<>();pianYiList.add(1);pianYiList.add(2);pianYiList.add(4);// 初始化数据for (int i = 0; i < number; i++) {System.out.println("请输入第" + (i + 1) + "个字符:");strList.add(scanner.nextLine());}for (int i = 0; i < strList.size(); i++) {char chArr[] = strList.get(i).toCharArray();StringBuilder secretStr = new StringBuilder();for (int j = 0; j < chArr.length; j++) {// 偏移量集合中的数据不够 字符去便宜的// System.out.println(j+"_"+pianYiList.size()+""+());if (j > (pianYiList.size() - 1) && j >= 3) {pianYiList.add(pianYiList.get(j - 1)+ pianYiList.get(j - 2) + pianYiList.get(j - 3));}int c = chArr[j];c = c + pianYiList.get(j);c = c > (int) 'z' ? c % (int) 'z' + 96 : c; // 96是小写字符a的前一位// 若z+1则结果为asecretStr.append((char) c);}System.out.println(secretStr.toString());}}
}
12.英文输入法
题目描述
主管期望你来实现英文输入法单词联想功能。
需求如下:
依据用户输入的单词前缀,从已输入的英文语句中联想出用户想输入的单词,按字典序输出联想到的单词序列,
如果联想不到,请输出用户输入的单词前缀。
注意:
英文单词联想时,区分大小写
缩略形式如”don’t”,判定为两个单词,”don”和”t”
输出的单词序列,不能有重复单词,且只能是英文单词,不能有标点符号
输入描述
输入为两行。
首行输入一段由英文单词word和标点符号组成的语句str;
接下来一行为一个英文单词前缀pre。
0 < word.length() <= 20
0 < str.length <= 10000
0 < pre <= 20
输出描述
输出符合要求的单词序列或单词前缀,存在多个时,单词之间以单个空格分割
| 输入 | 输出 | 说明 |
|---|---|---|
| I love you He | He | 从用户已输入英文语句”I love you”中提炼出“I”、“love”、“you”三个单词,接下来用户输入“He”,\n\n从已输入信息中无法联想到任何符合要求的单词,因此输出用户输入的单词前缀。 |
| The furthest distance in the world, Is not between life and death, But when I stand in front of you, Yet you don’t know that I love you. f | front furthest | 从用户已输入英文语句”The furthestdistance in the world, Is not between life and death, But when I stand in frontof you, Yet you dont know that I love you.”中提炼出的单词,符合“f”作为前缀的,有“furthest”和“front”,按字典序排序并在单词间添加空格后输出,结果为“front furthest”。 |
源码和解析
解析:
1.获取输入的所有字符,并拆分成子串数组(按空格) 注意处理缩略词don’t 为don和t
2.分别判断子串是否以用户输入的前缀开始
示例代码:
import java.util.ArrayList;
import java.util.Scanner;public class T12 {public static void main(String[] args) {System.out.println("请输入单词库(空格隔开):");Scanner scanner = new Scanner(System.in);String input1 = scanner.nextLine();System.out.println("请输入单词前缀:");String input2 = scanner.nextLine();ArrayList<String> wordList = new ArrayList<>();StringBuilder word = new StringBuilder();for (int i = 0; i < input1.length(); i++) {char c = input1.charAt(i);// 字符过滤if (!((c <= 'z' && c >= 'a') || (c <= 'Z' && c >= 'A'))) {if (word.length() > 0) {wordList.add(word.toString());word.setLength(0);}continue;};if (c == ' ') {if (word.length() > 0) {wordList.add(word.toString());word.setLength(0);}continue;}if (c == '\'') {if (word.length() > 0) {wordList.add(word.toString());word.setLength(0);}continue;}word.append(c);if (i == input1.length() - 1) {if (word.length() > 0) {wordList.add(word.toString());word.setLength(0);}}}boolean flag = false;// 是否找到for (String wd : wordList) {if (wd.startsWith(input2)) {flag = true;System.out.print(wd + " ");}}if (flag == false) {System.out.println(input2);}}
}
13.按索引范围翻转文章片段
题目描述
输入一个英文文章片段,翻转指定区间的单词顺序,标点符号和普通字母一样处理。
例如输入字符串”I am a developer. “,区间[0,3],则输出”developer. a am I”。
输入描述
使用换行隔开三个参数
第一个参数为英文文章内容即英文字符串
第二个参数为翻转起始单词下标(下标从0开始)
第三个参数为结束单词下标
输出描述
翻转后的英文文章片段所有单词之间以一个半角空格分隔进行输出。
| 输入 | 开始下标 | 结束下标 | 输出 | 说明 |
|---|---|---|---|---|
| I am a developer | 1 | 2 | I a am developer. | |
| hello world! | 0 | 1 | world! hello | 输入字符串可以在前面或者后面包含多余的空格,但是反转后的字符不能包括。 |
| I am a developer. | 0 | 3 | developer. a am I | 如果两个单词见有多余的空格,将反转后单词间的空格减少到只含一个。 |
| Hello! | 0 | 3 | EMPTY | 指定反转区间只有一个单词,或无有效单词则统一输出EMPTY。 |
源码和解析
解析:
1.获取输入字符 按空格拆分。符号按字母处理,那么就不用识别字符
2.指定反转区间只有一个单词,或无有效单词则统一输出EMPTY。
3.单词中的多余空格需要处理
4.按索引区间进行反转。若结束下标超过单词索引,那么就翻转到单词集最后一位
import java.util.ArrayList;public class T13 {public static void main(String[] args) {String input = "I am a developer.";int startIndex = 0;// 开始下标int endIndex = 3; // 结束下标String[] wordArr = input.split(" ");ArrayList<String> reverseList = new ArrayList<>();// 待反转数组for (int i = 0; i < wordArr.length; i++) {if (!wordArr[i].equals(" ")) {reverseList.add(wordArr[i]);}}if (endIndex > reverseList.size())endIndex = wordArr.length - 1;if (reverseList.size() <= 1) {System.out.println("EMPTY");return;}int count = 0;for (int i = 0; i < reverseList.size(); i++) {// 开始索引前和结束索引后的if (i < startIndex || i > endIndex) {System.out.print(reverseList.get(i) + " ");continue;}System.out.print(reverseList.get(endIndex - count) + " ");count++;}}
}
14. 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。 |
源码和解析
解析:
这个题首先要理解题目还是挺难的。小编拿到这个题读了三五遍还是理解不了题目要我们做个啥。后面也是参考别人的博客理解的题意。
首先要理解的一个概念就是 小端序
字节的排列方式有两个通用规则:大端序Big-Endian: 将数据的低位字节存放在内存的高位地址,高位字节存放在低位地址。这种排列方式与数据用字节表示时的书写顺序一致,符合人类的阅读习惯。
小端序Little-Endian: 将一个多位数的低位放在较小的地址处,高位放在较大的地址处,则称小端序。小端序与人类的阅读习惯相反,但更符合计算机读取内存的方式,因为CPU读取内存中的数据时,是从低地址向高地址方向进行读取的。
也就是说 小端序的排列方式 Len的两个字节需要交换顺序才能得到值的长度
比如02 00 = 其长度表示应该为 0002 也就是2位长度
示例中的码流可以做如下解析:
也就是每个tag对应的值 长度是变化的。我们需要依据tag后的两个字节长度推出后面的值。
示例代码:
public class T14 {public static void main(String[] args) {String objTag="31";String input="32 01 00 AE 90 02 00 01 02 30 03 00 AB 32 31 31 02 00 32 33 33 01 00 CC";String[] chArr = input.split(" ");for(int i=0;i<chArr.length;){String tag=chArr[i];int len=Integer.parseInt(chArr[i+2]+chArr[i+1]);// 小端序排列 还原长度时要交换位置StringBuilder value=new StringBuilder();i+=2;// tag 移动完for(int j=1;j<=len;j++){value.append(chArr[i+j]+" ");i++;//移动值}if(tag.equals(objTag)){System.out.println(value);break;}if(i<=(chArr.length-1))i++;// 移动tag}}
}
15.字符串筛选排序
题目描述
输入一个由N个大小写字母组成的字符串
按照ASCII码值从小到大进行排序
查找字符串中第K个最小ASCII码值的字母(k>=1)
输出该字母所在字符串中的位置索引(字符串的第一个位置索引为0)
k如果大于字符串长度则输出最大ASCII码值的字母所在字符串的位置索引
如果有重复字母则输出字母的最小位置索引
输入描述
第一行输入一个由大小写字母组成的字符串
第二行输入k ,k必须大于0 ,k可以大于输入字符串的长度
输出描述
输出字符串中第k个最小ASCII码值的字母所在字符串的位置索引
k如果大于字符串长度则输出最大ASCII码值的字母所在字符串的位置索引
如果第k个最小ASCII码值的字母存在重复 则输出该字母的最小位置索引
| 输入 | 输出 | 说明 |
|---|---|---|
| AbCdeFG 3 | 5 | 1.根据ASCII码排序 得到ACFGbde 第三位是F F在原字符串 AbCdeFG中索引为5 |
源码和解析
解析:
注意这里面涉及到原字符串和排序后的子串。还有就是两个位置(输入的第二个字符为位置,转换为索引是该数-1,例如第3个对应的位置值F 其索引为3-1=2 。还有一个输出值为目标字符F在字符串中第一次出现的索引。注意区分)
import java.util.Arrays;public class T15 {public static void main(String[] args) {String input = "AbCdeFG";int position = 3; // 排序后子串中的第n个char[] chArr = input.toCharArray();char obj = ' ';char[] newArr = chArr.clone();Arrays.sort(chArr);if (position > chArr.length) {obj = chArr[chArr.length - 1];// 取ASCC最大的字符} else {obj = chArr[position - 1];}for (int i = 0; i < newArr.length; i++) {if (obj == newArr[i]) {System.out.println(i);break;}}}
}
16.连续字母长度
题目描述
给定一个字符串,只包含大写字母,求在包含同一字母的子串中,长度第 k 长的子串的长度,相同字母只取最长的那个子串。
输入描述
第一行有一个子串(1<长度<=100),只包含大写字母。
第二行为 k的值
输出描述
输出连续出现次数第k多的字母的次数。
| 输入 | 输出 | 说明 |
|---|---|---|
| AAAAHHHBBCDHHHH 3 | 2 | 同一字母连续出现的最多的是A和H,四次; 第二多的是H,3次,但是H已经存在4个连续的,故不考虑; 下个最长子串是BB,所以最终答案应该输出2 |
| AABAAA 2 | 1 | 同一字母连续出现的最多的是A,三次; 第二多的还是A,两次,但A已经存在最大连续次数三次,故不考虑; 下个最长子串是B,所以输出1。 |
源码与解析
解析:
可以考虑将字符例如A与其出现的次数写入Map对象 ,A下次出现的次数如果比上次多,就替换,否则就不管 例如 AABAAA=》 {A:2}=>{A:2,B:1}=>{A:3,B:1}
将集合还原为字符串转换到List中 [AAA,B]
List按字符的长度来排序(大到小) 输出顺序对应的位置的字符即可
示例代码:
import java.util.ArrayList;
import java.util.Comparator;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;public class T16 {public static void main(String[] args) {String input = "AAAAHHHBBCDHHHH";int index = 1;String temStr = getSameCharacter(input);Map<Character, Integer> map = new HashMap<Character, Integer>();map.put(temStr.charAt(0), temStr.length());while (input.replaceFirst(temStr, "").length() > 0) {input = input.replaceFirst(temStr, "");temStr = getSameCharacter(input);if (map.get(temStr.charAt(0)) == null) {map.put(temStr.charAt(0), temStr.length());continue;}// 原来的小于当前 否则不换if (map.get(temStr.charAt(0)) < temStr.length()) {map.put(temStr.charAt(0), temStr.length());}}ArrayList<String> strList = new ArrayList<>();Set<Character> keySet = map.keySet();Iterator<Character> it = keySet.iterator();while (it.hasNext()) {Character character = it.next();Integer len = map.get(character);StringBuilder str = new StringBuilder();for (int i = 0; i < len; i++) {str.append(character);}strList.add(str.toString());}strList.sort(new Comparator<String>() {@Overridepublic int compare(String o1, String o2) {if (o1.length() > o2.length())return -1;if (o1.length() < o2.length())return 1;return 0;}});System.out.println(strList);System.out.println(strList.get(index - 1).length());// System.out.println(map);}// 取某个字符串中首字母连续出现字符public static String getSameCharacter(String str) {StringBuilder result = new StringBuilder();if (str.trim().length() == 0)return null;String firstCharacter = str.charAt(0) + "";while (str.startsWith(firstCharacter)) {result.append(firstCharacter);str = str.replaceFirst(firstCharacter, "");}return result.toString();}
}
17.拼接URL
题目描述
给定一个url前缀和url后缀,通过","分割 需要将其连接为一个完整的url
如果前缀结尾和后缀开头都没有/,需要自动补上/连接符
如果前缀结尾和后缀开头都为/,需要自动去重
约束:不用考虑前后缀URL不合法情况
输入描述
url前缀(一个长度小于100的字符串) url后缀(一个长度小于100的字符串)
输出描述
拼接后的url
| 输入 | 输出 | 说明 |
|---|---|---|
| /acm,/bb | /acm/bb | 无 |
| /abc,/bcd | /abc/bcd | 无 |
| /acd,bef | /acd/bef | 无 |
| , | / | 无 |
源码和解析
解析:
1.可以很轻松获得url的前缀和后缀
2.无论前缀后缀是否有/,都可以去掉
3.直接拼接即可
示例代码:
public class T17 {public static void main(String[] args) {String input = "/acd,bef";String wordArr[] = input.split(",");if (wordArr.length == 0) {System.out.println("/");return;}if (wordArr.length == 1) {System.out.println("/" + wordArr[0]);return;}String prefix = wordArr[0];if (prefix.startsWith("/"))prefix = prefix.replaceFirst("/", "");String suffix = wordArr[1];if (suffix.startsWith("/"))suffix = suffix.replaceFirst("/", "");System.out.println("/" + prefix + "/" + suffix);}
}
18.非严格递增连续数字序列
题目描述
输入一个字符串仅包含大小写字母和数字,求字符串中包含的最长的非严格递增连续数字序列的长度,(比如12234属于非严格递增连续数字序列)。
输入描述
输入一个字符串仅包含大小写字母和数字,输入的字符串最大不超过255个字符。
输出描述
最长的非严格递增连续数字序列的长度
| 输入 | 输出 | 说明 |
|---|---|---|
| abc2234019A334bc | 4 | 2234为最长的非严格递增连续数字序列,所以长度为4。 |
源码和解析
解析:
可以用双指针来做 根据自己需求来 如果对指针使用不是很擅长的。可以考虑不用指针
示例代码1:
public class T18 {public static void main(String[] args) {String input = "abc2234567019A334bc";int left = 0;int right = 0;int max = 0;for (int i = 0; i < input.length() - 1; i++) {if (input.charAt(right + 1) - input.charAt(right) == 1|| input.charAt(right + 1) - input.charAt(right) == 0) {right++;// 右指针右移一个} else {right++;if (right - left > max) {max = right - left;}left = right;}}System.out.println(max);}
}
示例代码2:
public class T18_1 {public static void main(String[] args) {String input = "abc2234019A33455bc";getPrefix(input);}// 获取字符串开始连续字符串public static void getPrefix(String input) {StringBuilder str = new StringBuilder();char lastCharacter = input.charAt(0);// 自后一个字符;str.append(lastCharacter);int max = 0;for (int i = 1; i < input.length(); i++) {if (input.charAt(i) - lastCharacter == 1|| input.charAt(i) - lastCharacter == 0) {str.append(input.charAt(i) + "");lastCharacter = input.charAt(i);} else {// System.out.println(str.toString()+"_");if (str.toString().length() > max) {max = str.toString().length();}str.setLength(0);// 清空str.append(input.charAt(i) + "");lastCharacter = input.charAt(i);}}System.out.println("最值:" + max);}
}
19.相对开音节
题目描述
相对开音节构成的结构为辅音+元音(aeiou)+辅音(r除外)+e,常见的单词有bike、cake等。
给定一个字符串,以空格为分隔符,反转每个单词中的字母,若单词中包含如数字等其他非字母时不进行反转。
反转后计算其中含有相对开音节结构的子串个数(连续的子串中部分字符可以重复)。
输入描述
字符串,以空格分割的多个单词,字符串长度<10000,字母只考虑小写
输出描述
含有相对开音节结构的子串个数,注:个数<10000
| 输入 | 输出 | 说明 |
|---|---|---|
| ekam a ekac | 2 | 反转后为 make a cake 其中make、cake为相对开音节子串,返回2。 |
| !ekam a ekekac | 2 | 反转后为!ekam a cakeke 因!ekam含非英文字符所以未反转,其中 cake、keke为相对开音节子串,返回2。 |
源码和解析
解析:
1.按空格拆分就比较简单了
2.判断是否包含非字母字符可以使用正则判断
3.开音节子串的判断(主要是要把所有的子串找出来 不遗漏)
3.1 注意只需要判断反转后的字符串。 不用反转来找
3.2 可以逐个找出开音节子串 (具体思路就是找到一个就把字符串的首字母去掉,接着在找。把所有可能的子串找出来装入List。可能会出现重复
3.3 从原始单词中找出List找到的开音节子串,找到一个就把开始索引换成下划线
3.4 把索引装入set 这样的话就可以得出一个单词中可能出现的所有子串
3.5 遍历求和即可
示例代码:
import java.util.ArrayList;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Set;
import java.util.regex.Matcher;
import java.util.regex.Pattern;public class T19 {public static void main(String[] args) {// new StringBuilder("cake a cafe cakekeke ekac").reverse().toString();String input = "!ekam a ekekac";String wordArr[] = input.split(" ");for (int i = 0; i < wordArr.length; i++) {String word = wordArr[i];// System.out.println(containNotCharacter(word));if (containNotCharacter(word) == false) {wordArr[i] = new StringBuilder(word).reverse().toString();}}int count = 0;for (String c : wordArr) {count += getRelativeNumber(c);}// 字符该反转的已反转// 相对开音节==》辅音+元音(aeiou)+辅音(r除外)+e// 辅音 除原因之外的字母System.out.println("结果:" + count);}public static int getRelativeNumber(String word) {StringBuilder tmpWord = new StringBuilder(word);Pattern pattern = Patternpile("[a-z&^aeiou]{1}[aeiou]{1}[a-z&^aeiour]{1}e");Matcher matcher = pattern.matcher(word);List<String> keySet = new ArrayList<>();while (matcher.find()) {// 可能是相对开音节的字符 还得看其出现的次数keySet.add(word.substring(matcher.start(), matcher.end()));word = word.replaceFirst(word.charAt(0) + "", "");matcher = pattern.matcher(word);}// 可能取到重复的Iterator<String> it = keySet.iterator();Set<Integer> indexSet = new HashSet<>();while (it.hasNext()) {String key = it.next();pattern = Patternpile(key);matcher = pattern.matcher(tmpWord.toString());while (matcher.find()) {indexSet.add(matcher.start());tmpWord.setCharAt(matcher.start(), '_');// 得一个就把开始索引换了}}return indexSet.size();}public static boolean containNotCharacter(String word) {Pattern pattern = Patternpile("[^a-z]+");Matcher matcher = pattern.matcher(word);return matcher.find();}
}
20.最远足迹
题目描述
某探险队负责对地下洞穴进行探险。探险队成员在进行探险任务时,随身携带的记录器会不定期地记录自身的坐标,但在记录的间隙中也会记录其他数据。探索工作结束后,探险队需要获取到某成员在探险过程中相对于探险队总部的最远的足迹位置。
仪器记录坐标时,坐标的数据格式为(x,y),如(1,2)、(100,200),其中0<x<1000,0<y<1000。同时存在非法坐标,如(01,1)、(1,01),(0,100)属于非法坐标。
设定探险队总部的坐标为(0,0),某位置相对总部的距离为:xx+yy。
若两个座标的相对总部的距离相同,则第一次到达的坐标为最远的足迹。
若记录仪中的坐标都不合法,输出总部坐标(0,0)。
备注:
不需要考虑双层括号嵌套的情况,比如sfsdfsd((1,2))。
输入描述
字符串,表示记录仪中的数据。
如:ferga13fdsf3(100,200)f2r3rfasf(300,400)
输出描述
字符串,表示最远足迹到达的坐标。如: (300,400)
| 输入 | 输出 | 说明 |
|---|---|---|
| ferg(3,10)a13fdsf3(3,4)f2r3rfasf(5,10) | (5,10) | 记录仪中的合法坐标有3个: (3,10), (3,4), (5,10),其中(5,10)是相距总部最远的坐标, 输出(5,10)。 |
| asfefaweawfaw(0,1)fe | (0,0) | 记录仪中的坐标都不合法,输出总部坐标(0,0) |
源码和解析
解析:
该题解决的核心就在从字符串中取出合法的坐标 使用合适的正则匹配可以使得问题变得简单。
示例代码:
import java.util.regex.Matcher;
import java.util.regex.Pattern;public class T20 {public static void main(String[] args) {String input = "ferg(03,100)a13fdsf3(3,04)f2r3rfasf(5,10)";// String input="asfefaweawfaw(0,1)fe";// String input="ferg(3,10)a13fdsf3(6,10)f2r3rfasf(5,10)";StringBuilder inputBuilder = new StringBuilder(input);// (3,10)√ (03,10) (1,01),(0,100) ×==>x,y坐标都不能0开头String reg = "\\([1-9]{1}[0-9]{0,2},[1-9]{1}[0-9]{0,2}\\)";Pattern pattern = Patternpile(reg);Matcher matcher = pattern.matcher(inputBuilder.toString());String objPosition = "(0,0)";int max = 0;while (matcher.find()) {String positionStr = input.substring(matcher.start(), matcher.end());inputBuilder.setCharAt(matcher.start(), '_');// 破坏原始结构中第一个满足的// 接着找第其他的...matcher = pattern.matcher(inputBuilder.toString());// System.out.println(positionStr);String xy[] = positionStr.replace("(", "").replace(")", "").split(",");int x = Integer.parseInt(xy[0]);int y = Integer.parseInt(xy[1]);if (x * x + y * y > max) {max = x * x + y * y;objPosition = positionStr;}}System.out.println(objPosition);}
}
本文标签: 华为OD机试(1
版权声明:本文标题:华为OD机试(1 内容由网友自发贡献,该文观点仅代表作者本人, 转载请联系作者并注明出处:https://www.betaflare.com/biancheng/1731193677a1598620.html, 本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,一经查实,本站将立刻删除。


发表评论