今日头条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);
}
}
原文地址:https://www.cnblogs.com/corvey/p/8638435.html
时间: 2024-10-06 00:31:03