今日頭條2017後端工程師實習生筆試題 - 題解
阿新 • • 發佈:2018-03-24
進制 true 字符串 從右到左 試題 imp 最終 create head
今日頭條2017後端工程師實習生筆試題
最大映射
題意 給n(不超過50)個字符串,每個字符串(長度不超過12)由A-J的大寫字符組成。要求將每個字符映射為0-9,使得每個字符串可以看作一個整數(不能有前導零),求這些字符串映射後得到數字的最大和值。(數據保證至少有一個字符不是任何字符串的首字母) 思路 根據字符所在的位置,累積統計每個字符的權值,從右到左權值分別為1, 10, 100, 1000..... 然後排序,從權值最小的到權值最大的依次映射為0-9,求和即為答案。 註意 由於每個字符串映射後得到的數字不能有前導零,因此需要記錄哪些字符成為過首字母,成為過首字母的字符最終不能映射為0。所以排序後需要判斷權值最小的字符是否成為過首字母,若是則需要從權值小到權值大找到第一個不為首字母的字符X,將它映射為0。在權值比X小的則依次晉級。
舉例
A | B | C | D | E | F | G | H | I | J | |
---|---|---|---|---|---|---|---|---|---|---|
首字母 | F | F | T | F | T | T | F | T | T | T |
權值 | 100 | 90 | 80 | 70 | 60 | 50 | 40 | 30 | 20 | 10 |
映射 | 9 | 8 | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
由於 J 成為過首字母,因此不能映射為 0
所以最終結果應為
A | B | C | D | E | F | H | I | J | G | |
---|---|---|---|---|---|---|---|---|---|---|
首字母 | F | F | T | F | T | T | T | T | T | F |
權值 | 100 | 90 | 80 | 70 | 60 | 50 | 30 | 20 | 10 | 40 |
映射 | 9 | 8 | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
木棒拼圖
題意 一個木棒集合,每根木棒知道長度,問能否用這些木棒構成一個面積大於0的簡單多邊形(不能自交)。數據有n次操作,每次操作要麽增加一根長度為x的木棒,要麽去掉一根長度為x的木棒,每次操作完後問剩下的木棒能否滿足上述條件。 思路 要使這些木棒能構成一個面積大於0的簡單多邊形,只需滿足最長的木棒短於剩下的所有木棒的總長。即多邊形近乎為一條直線。 因此只需構造一個集合,從小到大存放木棒,每次操作更新總長度,判斷 maxLen < sum - maxLen 即可。
魔法權值
題意
給n(不超過8)個字符串,每個字符串長度不超過20。把這些字符串全排列得到n!個字符串。一個字符串的權值等於把這個字符串循環左移 i 次後得到的字符串仍和原字符串全等的數量,i 的取值為 [1 , 字符串長度]。求這n!個字符串中有多少個權值為k。
思路
暴力解決。遞歸全排列得到所有字符串,每個字符串跑一遍求出k
import java.util.Scanner;
public class Main {
private static String[] input = new String[8];
private static String[] strs = new String[40320];
private static int n, k;
private static int cnt = 0;
private static void createString() {
class Iter {
boolean[] mark = new boolean[n];
void work(String prefix) {
boolean tag = false;
for (int i=0; i<n; ++i) {
if (mark[i] == false) {
tag = true;
mark[i] = true;
work(prefix + input[i]);
mark[i] = false;
}
}
if (tag == false) {
strs[cnt] = prefix;
++cnt;
}
}
}
new Iter().work("");
}
private static int workWeight(String str) {
char[] chars = str.toCharArray();
int ans = 1;
int len = chars.length;
for (int i=1; i<len; ++i) {
if (chars[i] == chars[0]) {
int j = 1;
for (; j<len; ++j) {
if (chars[(i+j)%len] != chars[j]) {
break;
}
}
ans += j == len ? 1 : 0;
}
}
return ans;
}
public static void main(String[] args) {
Scanner scan = new Scanner(System.in);
n = scan.nextInt();
k = scan.nextInt();
for (int i=0; i<n; ++i) {
input[i] = scan.next();
}
createString();
int ans = 0;
for (int i=0; i<cnt; ++i) {
if (workWeight(strs[i]) == k) {
++ans;
}
}
System.out.println(ans);
}
}
或與加
題意
給定兩個正整數 x, k (0 < x, k < 2 0000 0000),求第k個滿足 x + y = x | y 的 y (正整數)
思路
要使 x + y = x | y 則 x 和 y 的二進制表示1和1之間的位置應該是不重合的,即 x & y = 0
則把k的二進制表示依次對應到x的二進制表示上為0的位置,其余空位添上0則為答案
舉例 n = 5, k = 3
5 -> 0b 0101
3 -> 0b 0011
ans 0b 1010
(將k的1依次放到n上0的位置,其余空位添上0)
註意
由於x,k最大範圍為2億,因此極限情況為 x = k = 2 ^ 30 - 1 = 0b111...1111(連續30個1),則最終答案為0b111...11100000...0000(30個1接30個0),60位,因此最終結果需要用long表示。
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
Scanner input = new Scanner(System.in);
int x = input.nextInt();
int k = input.nextInt();
StringBuilder sb = new StringBuilder();
while (k > 0) {
if ((x & 1) == 1) {
sb.append(0);
} else {
sb.append(k & 1);
k >>= 1;
}
x >>= 1;
}
long ans = Long.parseLong(sb.reverse().toString(), 2);
System.out.println(ans);
}
}
今日頭條2017後端工程師實習生筆試題 - 題解