演算法-華為18-04-10筆試題
華為筆試題
今天做了下華為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());
}