目录
华为实习笔试题(2019年4月10日)
题目一:
题目二:
题目三:
华为笔试2019.9.7笔试题反思
第一题
第二题
第三题
帆软笔试(范围区间内数组的最大乘积)
一、范围区间内数组的最大乘积
360笔试题(2019/8/31)
一、寻找子串
二、散步
科大讯飞笔试(2019/9/12)
华为实习笔试题(2019年4月10日)
题目一:
题目描述:连续输入字符串,以空格键分割,输入字符串个数为n,请按长度为8拆分每个字符串后输出新的字符串数组,输出的字符串按照升序排列。长度不是8整数的在后面补0,空字符串不处理。第一个输入的字符串为个数n,后面的为n个待处理的字符串。
测试用例:
输入:
2 abc 1234567890
1
输出:
12345678 90000000 abc00000
注意:输出的字符串按照升序排列,意思是分割后的字符串,按照每个字符串的大小进行排序,由小到大。
第一版
package IMUHERO;
import java.util.Collections;
import java.util.LinkedList;
import java.util.Scanner;
public class Main{
public static void main(String[] args) {
Scanner scanner=new Scanner(System.in);
int n=scanner.nextInt();
String init=scanner.nextLine().trim();//.trim用于去除符号前后的空格
LinkedList<String>result=new LinkedList<>();
String[]arrS=init.split(" ");
for (int i=0;i<n;i++){
StringBuilder stb=new StringBuilder();
stb.append(arrS[i]);
if (stb.length()%8!=0){
stb.append("0000000");
}
while(stb.length()>=8){
result.add(stb.substring(0,8));
stb.delete(0,8);
}
}
Collections.sort(result);
for (int j=0;j<result.size();j++){
System.out.print(result.get(j)+" ");
}
}
}
2019.9.7修改完善:
import java.util.*;
public class DivideString {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
int len = scanner.nextInt();
LinkedList<String> list = new LinkedList<>();
for(int i=0;i<len;i++){
list.add(scanner.next());
}
LinkedList<String> res = new LinkedList<>();
while (!list.isEmpty()){
String s = list.removeFirst();
int i=0;
while ((i+1)*8<s.length()){
res.add(s.subSequence(i*8,(i+1)*8).toString());
i++;
}
if (i*8!=s.length()){
StringBuffer stb = new StringBuffer(s.substring(i*8));
int num = 8-(s.length()-i*8);
for (int j=0;j<num;j++){
stb.append("0");
}
res.add(stb.toString());
}
}
Collections.sort(res);
for (int i=0;i<res.size();i++){
System.out.print(res.get(i)+" ");
}
}
}
题目二:
给定一个字符串,字符串包含数字、大小写字母以及括号(包括大括号,中括号,小括号),括号可以嵌套,即括号里面可以出现数字和括号。
按照如下规则对字符串进行展开,不需要考虑括号不成对的问题,不考虑数字后面没有括号的情况,即 2a2(b)不考虑。
- 数字表示括号里的字符串重复的次数,展开后的字符串不包含括号
- 将字符串进行逆序展开 测试用例:
输入:
abc3(A)
- 输出:
AAAcba
解法一
//该解法存在问题
package IMUHERO;
import java.util.Scanner;
public class Main{
public static void main(String[] args) {
Scanner scanner=new Scanner(System.in);
String input=scanner.nextLine();
String output=getStr(input);
for (int i=output.length()-1;i>=0;i--){
System.out.print(output.charAt(i));
}
}
public static String getStr(String in){
int end=0;
StringBuilder stb=new StringBuilder();
for (int i=0;i<in.length();){
if (Character.isDigit(in.charAt(i))){
if (in.charAt(i+1)=='{'){
end=in.lastIndexOf('}');
}
else if (in.charAt(i+1)=='['){
end=in.lastIndexOf(']');
}
else if (in.charAt(i+1)=='('){
end=in.lastIndexOf(')');
}
for (int j=0;j<in.charAt(i)-'0';j++){
stb.append(getStr(in.substring(i+2,end)));
}
i=end+1;
}
else {
stb.append(in.charAt(i));
i++;
}
}
return stb.toString();
}
}
2019.9.7修改完善版:使用两个栈 leetcode测试通过
public String decodeString(String s) {
Stack<String> multi_stack = new Stack<>();
Stack<String>string_stack = new Stack<>();
StringBuffer res = new StringBuffer();
int multi = 0;
for (int i=0;i<s.length();i++){
if (s.charAt(i)>='0'&&s.charAt(i)<='9'){
multi = multi * 10 + Integer.parseInt(s.charAt(i) + ""); //用来解决十位数以上的情况
}
else if (s.charAt(i)=='['||s.charAt(i)=='{'||s.charAt(i)=='('){
string_stack.push(res.toString());
multi_stack.push(String.valueOf(multi));
multi =0;
res = new StringBuffer();
}
else if (s.charAt(i)==']'||s.charAt(i)=='}'||s.charAt(i)==')'){
StringBuffer tmp = new StringBuffer();
int cur_multi = Integer.parseInt(multi_stack.pop());
for (int j=0;j<cur_multi;j++){
tmp.append(res);
}
res.delete(0,res.length());
res.append(string_stack.pop()+tmp);
}
else {
res.append(s.charAt(i));
}
}
return res.reverse().toString();
}
public static void main(String[] args) {
InverseExpansionString ie = new InverseExpansionString();
String s ="5[a]2[bc]";
String s1 = "2[abc]3[cd]ef";
String s2 ="3[a2[c]]";
String s3 = "100[leetcode]"; //多位数字
String res = ie.decodeString(s3);
System.out.println(res);
}
2019.9.7 递归版本
class Solution {
Stack<Integer>stack = new Stack<>(); //单纯是用来存储下一个括号的下标
public String decodeString(String s) {
return decodeString(s,0);
}
//事实上也可以自定义一个Pair类,包含(StringBuffer,index),这里就不在累述
public String decodeString(String s,int index) {
StringBuffer res = new StringBuffer();
int multi = 0;
char cArray [] = s.toCharArray();
for (int i=index;i<cArray.length;i++){
char c = cArray[i];
if (c>='0'&&c<='9'){
multi = multi*10+c-'0';
}
else if (c=='['||c=='{'||c=='('){
String in = decodeString(s,i+1);
while (multi!=0){
res.append(in);
multi--;
}
i=stack.pop();
}
else if (c==']'||c=='}'||c==')'){
stack.push(i);
return res.toString();
}
else res.append(c);
}
return res.toString();
}
}
题目三:
题目三
题目描述:在N*M的地图上,每个点的海拔不同,从当前位置只能访问上下左右四个点且是没有访问过的点,此外下一步选择的点的海拔必须大于当前点。求从点A到点B一共有多少条路径,输出路数总数取余109109 10^9109。左上角的坐标为(0,0),右下角的坐标为(N-1,M-1)
测试用例:
输入:第一行为地图大小,下面n行为每个点的海拔,最后一行前两个为A坐标(x,y),后两个为B坐标(z,v)
4 5
0 1 0 0 0
0 2 3 0 0
0 0 4 5 0
0 0 7 6 0
0 1 3 2
123456
输出:
2
---------------------
(递归)and 记忆化搜索法:
//该版本没有标记是否isVisited
package IMUHERO;
import java.util.Arrays;
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
Scanner scanner =new Scanner(System.in);
int n=scanner.nextInt();//标记行数
int m=scanner.nextInt();//标记列数
int highMount[][]=new int[n][m];
for (int i=0;i<n;i++){
for (int j=0;j<m;j++){
highMount[i][j]=scanner.nextInt();
}
}
int start[]=new int[2];
int end[]=new int [2];
start[0]=scanner.nextInt();
start[1]=scanner.nextInt();
end[0]=scanner.nextInt();
end[1]=scanner.nextInt();
int [][]memo=new int [n][m];
for (int k=0;k<n;k++){
Arrays.fill(memo[k],-1);
}
int count=findPath(highMount,end,start[0],start[1],n,m,memo);
System.out.println(count);
}
public static int findPath(int[][]h,int[]end,int i,int j,int n,int m,int[][]memo){
if (i>=0 &&i<n &&j>=0 &&j<m &&i==end[0] &&j==end[1]){
return 1;
}
if (memo[i][j]!=-1)return memo[i][j];
int a=0,b=0,c=0,d=0;
if (i>=0 &&i<n &&j>=0 &&j<m &&i+1<n &&h[i+1][j]>h[i][j]){
a=findPath(h,end,i+1,j,n,m,memo);
}
if (i>=0 &&i<n &&j>=0 &&j<m &&i-1>0 &&h[i-1][j]>h[i][j]){
b=findPath(h,end,i-1,j,n,m,memo);
}
if (i>=0 &&i<n &&j>=0 &&j<m &&j+1<m &&h[i][j+1]>h[i][j]){
c=findPath(h,end,i,j+1,n,m,memo);
}
if (i>=0 &&i<n &&j>=0 &&j<m &&j-1>0 &&h[i][j-1]>h[i][j]){
d=findPath(h,end,i,j-1,n,m,memo);
}
memo[i][j]=a+b+c+d;
return a+b+c+d;
}
}
2019.9.7修改完善版:
public class climpUpMap {
static int move[][] = {{-1,0},{0,1},{1,0},{0,-1}};
static int memo[][] ;
static boolean[][] isVisited;
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
int rows = scanner.nextInt();
int cols = scanner.nextInt();
int [][] map = new int[rows][cols];
isVisited = new boolean[rows][cols];
memo = new int[rows][cols];
for (int i=0;i<rows;i++){
for (int j=0;j<cols;j++){
map[i][j] = scanner.nextInt();
}
}
int x0 = scanner.nextInt();
int y0 = scanner.nextInt();
int x1 = scanner.nextInt();
int y1 = scanner.nextInt();
//如果终点比起点还矮或者相等,表示没有路径可以到达
if (map[x0][y0]>=map[x1][y1]){
System.out.println(0);
}
else {
countPath(map,x0,y0,x0,y0,x1,y1);
System.out.println(memo[x0][y0]);
}
}
private static int countPath(int [][] map ,int i,int j,int x0,int y0,int x1,int y1){
if (map[i][j]==map[x1][y1]){
return 1;
}
if (memo[i][j]!=0){
return memo[i][j];
}
isVisited[i][j] = true;
int count = 0;
for (int k=0;k<4;k++){
int newI = i+move[k][0];
int newJ = j+move[k][1];
if (newI>=0&&newI<map.length &&newJ>=0&&newJ<map[0].length && !isVisited[newI][newJ]
&& map[newI][newJ]>map[i][j] ){
count +=countPath(map,newI,newJ,x0,y0,x1,y1)%109109;
isVisited[newI][newJ]=false;
}
}
memo[i][j] = count;
return memo[i][j];
}
}
华为笔试2019.9.7笔试题反思
第一题
输入一个数组
[ 8,7,1,2,3,4,5,2,2,5,6];
第一个数可以取[1-len/2],然后这个数作为下标a
接下去的数是a的值arr[a],以这个值为步数,往后走arr[a]步
求最少走多少步可以到达终点
以上数组的答案是:3
8 -> 7 ->2 ->6
解答:
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
String s = scanner.nextLine();
String[] c = s.split(" ");
int res = s.length();
int tmp = -1;
if (c.length==1){
System.out.println(1);
}
else {
for (int i=1;i<c.length/2;i++){
int j=i;
int count =1;
while (j<c.length-1){
j=j+(Integer.parseInt(c[j]));
count++;
}
if (j==c.length-1){
tmp =count;
res = Math.min(res,tmp);
}
}
if (res==s.length()) System.out.println(-1);
else System.out.println(res);
}
}
第二题
题目描述
dota游戏里面,召唤师可以控制冰雷火三种元素,并通过元表组合产生新的技能。现在我们修改了一张新的地图,地图中他能够控制n种元素,并且将m个元青围成-个圈组成个新技能(这m个元素通过旋转或反转,算作重复,如123、231、 312、 321、213、132都算重复) ,那么召唤师能组台多少技能
(2000>=n>=1 ,1<=m<=10000 ,由于结果可能很大,请将结果对00000007取余
输入描述:
n和m
输出描述:
组合的技能数
如:
输入:3,3
输出:[[1, 1, 1], [1, 1, 2], [1, 1, 3], [1, 2, 2], [1, 2, 3], [1, 3, 3], [2, 2, 2], [2, 2, 3], [2, 3, 3], [3, 3, 3]]
解答:(未通过,还没想到解决办法)
package IMUHERO;
import java.util.LinkedList;
import java.util.List;
import java.util.Scanner;
public class Main {
static LinkedList<List<Integer>>res = new LinkedList<>();
static int count=0;
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
int n = scanner.nextInt();
int k = scanner.nextInt();
if (n==0||k==0) System.out.println(0);
else {
LinkedList<Integer>list = new LinkedList<>();
Combine(n,k,1,list);
System.out.println(res);
System.out.println(count);
}
}
private static void Combine(int n,int k,int start,LinkedList<Integer>list){
if (list.size()==k){
res.addLast((LinkedList<Integer>)list.clone());
count = (count+1)%1000000007;
return;
}
for (int i=start;i<=n;i++){
list.addLast(i);
Combine(n,k,i,list);
list.removeLast();
}
return;
}
}
2019/9/12 使用ploya算法解决
package IMUHERO;
//华为第二题
import java.util.Scanner;
public class Main4 {
static int c ,s;
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
while (scanner.hasNext()){
c = scanner.nextInt();
s = scanner.nextInt();
long ans = polya();
System.out.println(ans);
}
}
static int gcd(int a,int b){
return b==0?a:gcd(b,a%b);
}
static long polya(){
int i,j;
long ans =0;
for (i=0;i<s;i++){
ans+=(long)Math.pow(1.0*c,gcd(s,i));
}
if(s%2!=0){
ans+=s*(long)Math.pow(1.0*c,s/2+1);
}
else{
ans+=s/2*(long)Math.pow(1.0*c,s/2);
ans+=s/2*(long)Math.pow(1.0*c,s/2+1);
}
long temp = ans/2;
return temp/s;
}
}
第三题
.题目描述
通讯行业上经常使用指标来记录某地区的业务数据,如小区用户切换请求次数的指标,小区用户切换请求成功次数的指标等。指标按类型分为基础指标和复杂指标。其中复杂指标由基础指标计算而来
如:小区用户切换成功率为复杂指标,计算公式为:小区用户切换成功率=小区用户切换请求成功次数/小区用户切换次数* 100;现在给每个指标赋予一个唯HD来替代中文描述, 使用中括号[括起来,对于公式中的常量则使用大括号0括起来;
如小区用户切换成率指标ID-1123654]、小区用户切换请求成功次数指标1D-|6598]、小区用户切换次数指标D-(6665]上述小区用户切换成功率公式可以表示为:[123654)-16598] 6665](100
要求:输入组复杂指标的计算公式以及公式中包含的基础指标的值,计算出指定指标的值并返回;
输入
[1234]=[12]+[34]*{50},[12]=[1]+[2]/{2};[1]=10,[2]=20,[34]=50;[1234]
输出:
[1234]的计算结果:2520
package IMUHERO;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.Scanner;
//[1234]=[12]+[34]*{50},[12]=[1]+[2]/{2};[1]=10,[2]=20,[34]=50;[1234]
public class Main1 {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
String s = scanner.nextLine();
String [] sArr = s.split(";");
String [] GS = sArr[0].split(",");
String [] KV = sArr[1].split(",");
String [] Value = sArr[2].split("");
HashMap<String,String> map = new HashMap();
for (int i=0;i<KV.length;i++){
String [] keyValue = KV[i].split("=");
String key = keyValue[0].substring(1,keyValue[0].length()-1);
String value = keyValue[1];
map.put(key,value);
}
for (int i=GS.length-1;i>=0;i--){
String [] keyValue = GS[i].split("=");
String key = keyValue[0].substring(1,keyValue[0].length()-1);
LinkedList<String>list = new LinkedList<>();
String val = keyValue[1];
for (int m=0;m<val.length();m++){
if (val.charAt(m)=='['){
int n=m;
while (val.charAt(n)!=']')n++;
String Skey = val.substring(m+1,n);
list.addLast(map.get(Skey));
m=n;
}
else if (val.charAt(m)=='{'){
int n=m;
while (val.charAt(n)!='}')n++;
list.addLast(val.substring(m+1,n));
m=n;
}
else list.addLast(String.valueOf(val.charAt(m)));
}
while (!list.isEmpty()){
if (list.size()==1){
map.put(key,list.removeFirst());
break;
}
int one = Integer.parseInt(list.removeFirst());
String sign1 = list.removeFirst();
int two = Integer.parseInt(list.removeFirst());
if (sign1.equals("+")||sign1.equals("-")) {
if (!list.isEmpty()){ //判断+、-之后是*、/
String sign2 = list.getFirst();
while (!list.isEmpty()&&sign2.equals("/")||sign2.equals("*")){
sign2 = list.removeFirst();
int three = Integer.parseInt(list.removeFirst());
if (sign2.equals("/")){
list.addFirst(String.valueOf(two/three));
}
else {
list.addFirst(String.valueOf(two*three));
}
two = Integer.parseInt(list.removeFirst());
if (!list.isEmpty())sign2 = list.getFirst();
else sign2="empty"; //表示链表已经计算完成,直接跳出
}
}
if (sign1.equals("+")){
list.addFirst(String.valueOf(one+two));
}
else {
list.addFirst(String.valueOf(one-two));
}
}
else {
if (sign1.equals("/")){
list.addFirst(String.valueOf(one/two));
}
else {
list.addFirst(String.valueOf(one/two));
}
}
}
}
StringBuffer stringBuffer = new StringBuffer();
for (String c:Value){
if (!c.equals("[")&&!c.equals("]")){
stringBuffer.append(c);
}
}
// System.out.println(stringBuffer);
System.out.println(map.get(stringBuffer.toString()));
}
}
帆软笔试(范围区间内数组的最大乘积)
一、范围区间内数组的最大乘积
输入:
-3 -5 2 -4
输出
30
解析:
index从0-2,-3*-5*2=30,是连续范围内乘积最大的区间
package IMUHERO;
import java.util.Scanner;
public class Main {
private static int max3(int a,int b,int c){
return Math.max(a,Math.max(b,c));
}
private static int min3(int a,int b,int c){
return Math.min(a,Math.min(b,c));
}
private static int maxMultiply(int [] arr){
//数组长度为0最开始已经判断过,此处不需要担心
int [] maxArr = new int[arr.length];
int [] minArr = new int[arr.length];
maxArr[0] = 0;
minArr[0] = 0; //用来对负数进行处理
int res = arr[0];
for (int i=1;i<arr.length;i++){
maxArr[i] = max3(arr[i],arr[i]*maxArr[i-1],arr[i]*minArr[i-1]);
minArr[i] = min3(arr[i],arr[i]*maxArr[i-1],arr[i]*minArr[i-1]);
if (res<maxArr[i])res = maxArr[i];
}
return res;
}
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
int len = scanner.nextInt();
if (len==0){
System.out.println(0);
}
else {
int[] arr = new int[len];
for (int i=0;i<len;i++){
arr[i] = scanner.nextInt();
}
int res = maxMultiply(arr);
System.out.println(res);
}
}
}
360笔试题(2019/8/31)
一、寻找子串
题目有漏洞,只要判断重复的字符个数即可得出答案,直接上代码
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
String s = scanner.nextLine();
TreeMap<Character,Integer> map = new TreeMap<>();
int len = s.length();
int count = 0;
for (int i = 0;i<len;i++){
char c = s.charAt(i);
if (!map.containsKey(c)){
map.put(c,1);
if (count==0)count++;
}
else{
int curCount = map.get(c);
map.put(c,curCount+1);
if (curCount+1>count)count=curCount+1;
}
}
System.out.println(count);
}
二、散步
解法一:
从前往后的dfs
package IMUHERO;
import java.util.Scanner;
import java.util.TreeSet;
public class Main{
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
int N = scanner.nextInt();
int mes = scanner.nextInt();
int [] arr = new int[mes];
for (int i = 0;i<mes;i++){
arr[i]=scanner.nextInt();
}
TreeSet<Integer>set = new TreeSet<>(); //使用TreeSet用来去除终点重复的情况
for (int s=1;s<=N;s++){
dfs(arr,0,s,set,N);
}
System.out.println(set.size());
}
//从前往后的算法:
private static void dfs(int[]arr,int i,int s,TreeSet<Integer>set,int N){
if (i==arr.length){
set.add(s);
return ;
}
if (s+arr[i]<=N){
dfs(arr,i+1,s+arr[i],set,N);
}
if (s-arr[i]>=1){
dfs(arr,i+1,s-arr[i],set,N);
}
}
}
解法二:
从后往前的算法:
package IMUHERO;
import java.util.Scanner;
import java.util.TreeSet;
public class Main{
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
int N = scanner.nextInt();
int mes = scanner.nextInt();
int [] arr = new int[mes];
for (int i = 0;i<mes;i++){
arr[i]=scanner.nextInt();
}
int count =0;
for (int s=1;s<=N;s++){
if (dfs2(arr,arr.length-1,s,N)){
count++;
}
}
System.out.println(count);
}
//从后往前的算法:
private static boolean dfs2(int[]arr,int index,int e,int N){
//使用index<0而不是使用index==-1,可以防止数组为空的情况
if (index<0){
return true;
}
//先判断是否能走才进行
if (e-arr[index]>=1){
if (dfs2(arr,index-1,e-arr[index],N))
return true;//剪枝,有一个成功就返回true
}
if (e+arr[index]<=N){
if (dfs2(arr,index-1,e+arr[index],N))
return true;//剪枝,有一个成功就返回
}
return false;//以上都不满足,直接返回false
}
}
科大讯飞笔试(2019/9/12)
第一题
两个大整数相加:
(据说是两行输入,但是题目实例给的是一行,无语......
不想改了,含义是一行的,只是Scanner有所不同而已)
package IMUHERO;
import java.util.Scanner;
public class Mainkeda {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
String s = scanner.nextLine(); //一行内输入两个长数字
String[]sArr =s.split(" ");
String s1 = sArr[0];
char[] c1 = s1.toCharArray();
String s2 = sArr[sArr.length-1];
char[] c2 = s2.toCharArray();
int carry = 0;
int [] res = new int[Math.max(c1.length,c2.length)+1];
// int i=Math.max(c1.length,c2.length)-1;
int i=0;
for (;i<c1.length||i<c2.length;i++){
int a , b;
a=(i<c1.length)?c1[c1.length-1-i]-'0':0;
b=(i<c2.length)?c2[c2.length-1-i]-'0':0;
res[Math.max(c1.length,c2.length)-i] = (a+b+carry)%10;
carry=(a+b+carry>=10)?1:0;
}
if (carry==1){
res[i+1]=carry;
}
for (int j=0;j<res.length;j++){
if (j==0&&res[j]==0)continue;
System.out.print(res[j]);
}
}
}
第二题:
输入:aabb
输出:2a2b
注:只含有一个字符不用输出数字,如:aabbc = > 2a2bc
package IMUHERO;
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
String s = scanner.nextLine();
if (s.length()==0||s==null) System.out.println("");
else {
StringBuilder stb = new StringBuilder();
for (int i=0;i<s.length();i++){
char c = s.charAt(i);
int size = 1;
for (int j=i+1;j<s.length();j++){
if (s.charAt(j)==c){
size++;
i=j;
}
else {
break;
}
}
if (size!=1)stb.append(size);
stb.append(c);
}
System.out.println(stb.toString());
}
}
}