华为笔试题
今天做了下华为10号的笔试和3号完全不是一个难度啊,果然是表面一批。
1.字符串调整
题目:给定一个字符串,根据字符串内每个字符出现的次数,按照ASCII码来重新调整字符串输出。
例:
输入为eeefgghhh则
- e,3次
- f,1次
- g,2次
- h,3次
输出为efghegheh
解题思路
- 统计每个字符出现次数
- 把每个字符按照ASCII的自然顺序排序
依序输出,如果本次输出当前字符数量为0即已经在前面用完了则不输出这个字符
1,2步可以用一个TreeMap实现,键值对记录每个字符的次数,同时TreeMap按照键排序(键为字符),则所得顺序正好是字符的ASCII码顺序(从小到大)
代码
public static void solve(String str){
//定义一个TreeMap按照键值的自然顺序对键值对排序
Map<Character, Integer> map = new TreeMap<>();
int max = 0;//记录最大的字符数,之后循环次数就是最大字符数
for(int i = 0;i < str.length();i++){//遍历字符串记录
final char c = str.charAt(i);
int now = map.getOrDefault(c, 0);//获得之前的出现次数,不存在返回0
max = Math.max(max, now + 1);//如果大于最大值跟新最大字符数
map.put(c, now + 1);
}
Set<Map.Entry<Character, Integer>> sets = map.entrySet();
StringBuilder sb = new StringBuilder();
for(int i = 0;i < max;i++) {
for (Map.Entry<Character, Integer> entry : sets) {
int times = entry.getValue();
char c = entry.getKey();
if(times > 0){//还有剩余则加入字符串
sb.append(c);
entry.setValue(times - 1);//减去一个
}
}
}
System.out.println(sb.toString());
}
2.Jump
题目:LeetCode原题(45.Jump Game 2),给定一个数组从下标0开始,每次能跳的最大距离为当前位置值,问最少几次能到达数组最后
例
输入:2,3,2,1,2,1,5
输出3, 2-3-2-5 或 2-2-2-5
解题思路
贪心法,计算出每一步能到达的最远距离,如果这个距离大于等于数组最后一个元素下标那当前步数就是从头到达尾的最小步数
例如2,3,2,1,2,1,5(下标为0,1,2,3,4,5,6),第一步最远走到2,所以第二步最远距离由下标1和下标2元素计算(1 + 3 和2+2的最大值 4),第三步最远由下标3和下标4(上一步最远距离)计算,以此类推直到该步最远距离大于等于最后一个元素下标。
代码
public static void solve(int[] arr){
//step:当前步数,max:当前能到达的最远下标,current:临时记录每步能到达的最远下标,pos遍历数组的位置
int step = 1, max = arr[0],current = 0, pos = 1;
final int len = arr.length - 1;
while(max < len){//最远没能到达最后位置时还要走
step++;
current = 0;
for(;pos <= max;pos++){//每次的开始都是上一次最后位置的下一个,一直计算到上一步的最远距离位置
current = Math.max(current, arr[pos] + pos);//记录当前步能到的最远位置
}
max = current;
}
System.out.println(step);
}
3.字符串乘法
题目:给定两个字符串里面每个字符都是’0’-‘9’之间,求两个字符串的乘积
例
输入:”1234”,”4321”
输出:”5332114”
解题思路
这是一个典型的大数相乘的问题,只要依照乘法的规则按位相乘后相加即可,为了方便得出结果我们需要作如下工作:
- 用数组来记录每一位结果,同时能方便的进行错位相加
- 由于输出的是字符串而计算是从最后一位的结果开始的所以为了方便倒叙输出得到答案需要在保存遍历相乘的每一位结果时倒序保存
代码
public static void solve(String s1, String s2){
int len1 = s1.length(), len2 = s2.length();
int[] num = new int[len1 + len2];//用于记录结果,n位数乘m位数结果不会超过n+m位
for(int i = 0;i < len1;i++){//遍历按位乘
final int inow = s1.charAt(len1 - i - 1) - '0';//计算当前位对应的整数,注意乘法是从最后一位开始计算的
int temp = 0;//记录当前计算值的进位
for(int j = 0;j < len2;j++){
int jnow = s2.charAt(len2 - j - 1) - '0';
int now = inow * jnow;
temp = temp + num[i+j] + now;//num[i+j]就是为了错位相加
num[i+j] = temp % 10;//当前位的值为计算的个位
temp /= 10;//进位
}
num[i + s2.length()] = temp;//如果最后进位为1说明前面要多一位了
}
int i = len1 + len2 - 1;//逆序输出
while(i > 0 && num[i] == 0)//跳过前面的0
i--;
StringBuilder sb = new StringBuilder();
while(i >= 0){
sb.append(num[i--]);
}
System.out.println(sb.toString());
}