华为机试题——该警醒了,骚年
因一次机试,随便写些东西,以此次之失误鞭策自己,水贴一篇,没什么知识分享,诸位大大可以选择无视O(∩_∩)O哈哈~
2016.03.27下午参加华为机试,简单扫了一眼几个题的标题,选择了一道字符串问题,其实该题非常非常的简单,可以说是简单的不能再简单了,而且有很多种解法,上机时我选择了直接借用java提供的一些函数,以为自己能很快解决问题,结果却卡了很久,机子上测试时一直没能通过
晚上回到寝室,改了一下前面的代码,解题方法没变,经测试应该是正确的
具体题目记不大清楚了,题目大意是:输入一字符串,若该字符串中间包含"*",去掉"*"后输出;若该字符串首字符或尾字符为"*",则保留该处的"*";若该字符串不包含"*"或包含其他字符,可直接输出
(是不是简单的不要不要的)
第一次提交代码如下(主要部分):
针对上述代码,在机子上测试时一直没通过,且针对如下测试数据有如下的报错,定位到代码中第29行,一直没弄明白为什么报错。
在很长时间没找到错误的情况下,就有了第一次提交
提交之后显示答案错误,于是简单看了一下提交的代码,发现编码时的辅助输出语句没有注释掉,注释掉了那一句辅助输出语句就第二次提交了,依然显示答案错误,此时不敢轻易提交了
反复改来改去,突然想起了星号(*)是特殊字符,修改之后测试时依然不能输出正确结果,此时代码如下:
因为花了很长时间这道题还没做出来有些慌乱,于是暂时放着去做第三题了,第三题依然简单的不要不要的,做完第三题回头再来看这道题目,过了好久还是没能解决这个问题,此时脑袋有些糊涂了以至于忘了只有三次提交机会,又提交了一次,结果可想而知
这之后点开第一题,有一些思路,但感觉正确解题估计得花一段时间,此时机房内小伙伴们已经走了不少,距考试结束已经没多少时间了,再者心情有些低落,放弃了继续作答
总结这次机试失误之因:
(1)粗心:
A.开始选择做这个字符串的题目之前没有将几个题分别简单地浏览一遍,不然肯定会先做第三题,因为该题简单不得了,要知道做出一题之后肯定会自信不少,且心态肯定会平静很多
B.一些编码时的辅助输出语句,提交时没注释掉,浪费一次作答机会(每题只可提交三次)
(2)基础不够扎实:
A.对一些函数不熟悉,刚开始使用split()方法来分割字符串时没注意到星号(*)是特殊字符
B.将split()方法返回的字符串数组转换为字符串时出错,我在代码中直接打印输出该字符串数组:System.out.print(line.split("\\*"));,感觉自己当时是不是傻了,如果静下心来从简单分析一下输出信息就应该知道怎么回事了,当时的我看到不是自己想要的输出,就匆忙去修改代码
(3)心态不好:
A.当花很长时间还没有解决出现的问题时没有及时放弃原来的解题方法,尽管此时我知道还有什么方法可以用来解答该问题
B.因长时间没有找到出错的原因而有些慌张,对运行输出的非预期结果或报的错误没有进行很细致的分析就忙着去修改代码,且前后测试没有使用同一数据,以至于每次错误定位到不同的代码行(应该是这次机试最大的失误吧),然而却不知道此时自己离成功只有一步之遥,只需要修改原代码将split()方法返回的字符串数组进行遍历拼接转换为字符串即可
晚上修改后代码如下:
package com.test; import java.util.*; public class Main { /** Creates a new instance of Main */ public Main() { } public static void main(String[] args) { Scanner scanner=new Scanner(System.in); String line=scanner.next(); // System.out.println("输入的字符串是:"+line); if(line.contains("*")){//字符串中包含"*" // System.out.println("字符串中包含*"); if(line.startsWith("*")||line.endsWith("*")){//字符串在首尾位置包含"*" int end=line.length(); if(end==1){//字符串包含"*",且其长度为1 System.out.print(line); }else{ String ss=""; if(line.startsWith("*")&&line.endsWith("*")){ String strarray=line.substring(1,end-1); // System.out.print("子串为:"+strarray); String[] str=strarray.split("\\*"); for(int i=0;i<str.length;i++){ ss+=str[i]; } System.out.print("*"+ss+"*"); } if(line.startsWith("*")&&!line.endsWith("*")){ String strarray=line.substring(1,end); // System.out.print("子串为:"+strarray); String[] str=strarray.split("\\*"); for(int i=0;i<str.length;i++){ ss+=str[i]; } System.out.print("*"+ss); } if(!line.startsWith("*")&&line.endsWith("*")){ String strarray=line.substring(0,end-1); // System.out.print("子串为:"+strarray); String[] str=strarray.split("\\*"); for(int i=0;i<str.length;i++){ ss+=str[i]; } System.out.print(ss+"*"); } } }else{//字符串中包含"*",但不在首尾位置 System.out.print(line.replaceAll("\\*","")); } }else{//字符串中不包含"*" System.out.print(line); } } }
我使用上述代码测试了一些数据均可得到正确结果,虽然还有很多可以优化的地方(如代码冗余等),但此处就不再展示了
贴出几组测试数据(输入):
* ** *** ****** *aaa*bb*c*
其对应结果应该如下(输出):
* ** ** ** *aaabbc*
还有一些其他解决方案应该更为简单快捷,比如下面这种(注意此方案循环中i的增减控制):
package com.test; import java.util.Scanner; public class Test { public static void main(String[] args){ Scanner scanner=new Scanner(System.in); String line=scanner.next(); StringBuffer str=new StringBuffer(line); for(int i=1;i<str.length()-1;i++){ if(str.charAt(i)=='*'){ str.deleteCharAt(i); i--; System.out.println(str.length()); } } System.out.println(str); } }
原本很简单的一次机试,其结果却让我对自己感到很失望,誓曰:君需更谨慎,此次失误不可再;君当更努力,夯基迎难不可阻!
感觉此文有些污了诸位大大的眼,请勿见怪哦(~ o ~)~zZ
===========看到园友评论,此处贴出java中的字符串分割函数:java.lang.string.split 的简单使用示例,以飨园友=============
Java中的我们可以利用split把字符串按照指定的分割符进行分割,然后返回字符串数组,下面是string.split的用法实例及注意事项:
split() 方法:将一个字符串分割为子字符串,然后将结果作为字符串数组返回。
使用方法如下:
stringObj.split([separator,[limit]])
参数解说:
stringObj:必选项,要被分解的 String 对象或文字,该对象不会被split方法修改。
separator:可选项,字符串或正则表达式对象,它标识了分隔字符串时使用的是一个还是多个字符。如果忽略该选项,返回包含整个字符串的单一元素数组。
limit :可选项,该值用来限制返回数组中的元素个数(也就是最多分割成几个数组元素,只有为正数时有影响)
示例1:
String str="Java string split test";
String[] strarray=str.split(" ");
for (int i = 0; i < strarray.length; i++){
System.out.println(strarray[i]);
}
输出如下:
Java
string
split
test
示例2:
String str="Java string split test";
String[] strarray=str.split(" ",2);//使用limit,最多分割成2个字符串
for (int i = 0; i < strarray.length; i++){
System.out.println(strarray[i]);
}
输出如下:
Java
string split test
示例3:
String str="192.168.0.1";
String[] strarray=str.split("\\."); //注意此处不能写为String[] strarray=str.split(".");
for (int i = 0; i < strarray.length; i++) {
System.out.println(strarray[i]);
}
输出如下:
192 168 0 1
经验分享:
1、若分隔符为“.”、“|”、“*”、“+”等转义字符时,直接使用str.split(".")会抛出异常,都必须在前面加"\\",如split(\\|);
2、如果用"\"作为分隔,就得写成这样:String.split("\\\\"),因为在Java中是用"\\"来表示"\"的,自定义字符串是这样的:String Str="a\\b\\c";
3、如果在一个字符串中有多个分隔符,可以用"|"作为连字符,比如:String str="Java string-split#test",可以用Str.split(" |-|#")把每个字符串分开;
4、split 方法的结果是一个字符串数组,在 stingObj 中每个出现 separator 的位置都要进行分解,separator不作为任何数组元素的部分返回。
示例4:
String str="192\\168-0.1";
String[] strarray=str.split("\\\\|-");
for (int i = 0; i < strarray.length; i++) {
System.out.println(strarray[i]);
}
输出如下:
192 168 0.1
=============跟贴出一道华为机试题,园友可以小小开动一下大脑(应该不算泄题吧O(∩_∩)O哈哈~)===============
题目大意:有一些定序的字符序列:a,b,c,...,z,aa,ab,...,az,ba,...,bz,...,zz,aaa,aab,...,aaz,...,zzz,...,当输入为aa,对应输出为27,;当输入为ba,对应输出为53。现在随意输入该字符序列中的某一字符串(假设该字符串长度不超过6位),请打印对应输出。
下面贴出我的代码,仅供批评(⊙o⊙)
import java.util.Scanner; public class Test { public static void main(String[] args){ Scanner scanner=new Scanner(System.in); int sum=0; while(scanner.hasNext()){ String str=scanner.next(); //对得到的字符串进行处理,计算bacd的规律为:dx1+cx26+ax26x26+bx26x26x26 sum=change(str); System.out.println(sum); } } private static int change(String s){ char[] str=s.toCharArray(); int length=s.length(); char[] ss=new char[length]; for(int k=0,j=length-1;k<length;k++){//反转字符串 ss[k]=str[j--]; } char[] base={'a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v','w','x','y','z'}; int sum=0; for(int i=0;i<length;i++){//计算 for(int j=0;j<26;j++){ if(ss[i]==base[j]){ sum=sum+(j+1)*operation(i); break; } } } return sum; } private static int operation(int k){//26的平方运算 int sum=1; for(int i=1;i<=k;i++){ sum=sum*26; } return sum; } }
一组测试数据如下:
输入: 输出: bc 55 aaa 703 zzzzzz 321272406