1. 程式人生 > >今日頭條2017後端工程師實習生筆試題 - 題解

今日頭條2017後端工程師實習生筆試題 - 題解

進制 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後端工程師實習生筆試題 - 題解