算法面试题-今日头条2017客户端工程师实习生笔试题4:或与加

今日头条2017客户端工程师实习生笔试题

题目:

这个题做到最后,时间不是很够,题目内容比较简单,求出第k个正整数符合x+y=x|y,然而这个k的取值范围非常大(k<=2000000000),所以可以不用考虑穷举法,当然,时间不够的话写个穷举试试运气也可以。

穷举法:

 1 import java.util.Scanner;
 2
 3 /**
 4  * Created by Administrator on 2016/9/6.
 5  */
 6
 7 public class Main {
 8     public static void main(String[] args) {
 9         Scanner scanner = new Scanner(System.in);
10         int x = scanner.nextInt();
11         int k = scanner.nextInt();
12         int n = 0;
13         int result = 0;
14         for (int i = 1; i <= 2000000000; i++) {
15             if ((x + i) == (x | i)) {
16                 n += 1;
17             }
18             if (n == k) {
19                 result = i;
20                 break;
21             }
22         }
23         System.out.println(result);
24     }
25 }

这里提交会提示超时,所以这个算法是不行的,比较循环的次数太多。

第一个想法是能不能减少循环次数,但是考虑到要求第k个,也就是不能省略掉其中一些否则会遗漏,所以只能考虑能否不使用循环求得。

因为这里用到了位运算,所以可以通过二进制来演算一下。

假设数据x=5,k=1的时候,y=2,分别用二进制进行表示:

5D = 0101B

2D = 0010B

7D = 0111B

这里其实已经可以发现规律了。

x+y是把x和y每一个二进制位进行相加,1+1就进位

x|y则是每个二进制位置对应的进行或运算(有1得1)

这个题目中,x的值是固定的,也就是x的二进制数中1的位置和数目是固定的,所以进行或运算的时候,结果中对应的位上都应该是1

现在考虑相加的情况,假设y与x中某一对应的位置都是1,就需要进行进位,也就是这个位置会变成0,显然x+y!=x|y。

考虑x中0的影响,因为在相加或者或运算的时候,0都不会影响到运算结果,所以结论很显然:

yB的对应于xB上所有为1的位均为0,则必有x+y=x|y。

现在考虑如何得到第k个。

因为有上面的规律,我们可以得知,y中为1的位只能对应于x中为0的位。

这里就很简单了,我们只需要求出k的二进制值,并且把这个二进制的值从低位逐个填入x为0的位即可得到相加的结果。

如:5+2=5|2=7 k=1

5D = 0101B

1D = 0001B

我们把1的二进制填入至x的二进制为0的地方则能得到0111B,也就是十进制的7。7-5=2,就能得到y的值。

再举一个例子:x=5, k=2

5D = 0101B

2D = 0010B

把2的二进制从低位开始填入5的二进制数中为0的地方,即可得到1101B,也就是13,所以y=13-5=8。

实际上,我们只需要把x中对应为1的地方改为1,就能直接得到y的值,相当于减去x。

所以我们在实际构造的时候,可以这样做:

逆序遍历x的每一位

  如果为1,则往结果的头部填充一个0(减法)

  否则将k中的最后一位填入结果的头部,并退出k的最后一位,此时如果k已经为空,则退出遍历。

  判断x是否已经遍历完,如果是,将k剩余的位一次填充到结果的头部。

AC代码:

 1 import java.util.Scanner;
 2
 3 /**
 4  * Created by Administrator on 2016/9/6.
 5  */
 6
 7 public class Main {
 8     public static void main(String[] args) {
 9         Scanner scanner = new Scanner(System.in);
10         int x = scanner.nextInt();
11         int k = scanner.nextInt();
12         String x_str = Integer.toBinaryString(x);
13         String k_str = Integer.toBinaryString(k);
14         StringBuilder sb = new StringBuilder();
15         int pointer = k_str.length() - 1;
16         for (int i = x_str.length() - 1; i >= 0; i--) {
17             if (x_str.charAt(i) == ‘1‘) {
18                 sb.insert(0, "0");
19             } else {
20                 sb.insert(0, k_str.charAt(pointer));
21                 pointer -= 1;
22                 if (pointer < 0) {
23                     break;
24                 }
25             }
26             if (i == 0 && pointer >= 0) {
27                 sb.insert(0, k_str.substring(0, pointer + 1));
28             }
29         }
30         System.out.println(Long.parseLong(sb.toString(), 2)); // 使用Long是因为结果可能会超过Integer的表示范围
31     }
32 }
时间: 2024-10-09 23:42:05

算法面试题-今日头条2017客户端工程师实习生笔试题4:或与加的相关文章

今日头条2017后端工程师实习生笔试题 - 题解

今日头条2017后端工程师实习生笔试题 最大映射 题意 给n(不超过50)个字符串,每个字符串(长度不超过12)由A-J的大写字符组成.要求将每个字符映射为0-9,使得每个字符串可以看作一个整数(不能有前导零),求这些字符串映射后得到数字的最大和值.(数据保证至少有一个字符不是任何字符串的首字母) 思路 根据字符所在的位置,累积统计每个字符的权值,从右到左权值分别为1, 10, 100, 1000..... 然后排序,从权值最小的到权值最大的依次映射为0-9,求和即为答案. 注意 由于每个字符串

今日头条2017后端工程师实习生笔试题

第二题: [编程题] 木棒拼图 有一个由很多木棒构成的集合,每个木棒有对应的长度,请问能否用集合中的这些木棒以某个顺序首尾相连构成一个面积大于 0 的简单多边形且所有木棒都要用上,简单多边形即不会自交的多边形. 初始集合是空的,有两种操作,要么给集合添加一个长度为 L 的木棒,要么删去集合中已经有的某个木棒.每次操作结束后你都需要告知是否能用集合中的这些木棒构成一个简单多边形. 输入描述: 每组测试用例仅包含一组数据,每组数据第一行为一个正整数 n 表示操作的数量(1 ≤ n ≤ 50000)

今日头条2017后端工程师笔试题

1.最大映射 有 n 个字符串,每个字符串都是由 A-J 的大写字符构成.现在你将每个字符映射为一个 0-9 的数字,不同字符映射为不同的数字.这样每个字符串就可以看做一个整数,唯一的要求是这些整数必须是正整数且它们的字符串不能有前导零.现在问你怎样映射字符才能使得这些字符串表示的整数之和最大? 输入描述: 每组测试用例仅包含一组数据,每组数据第一行为一个正整数 n , 接下来有 n 行,每行一个长度不超过 12 且仅包含大写字母 A-J 的字符串. n 不大于 50,且至少存在一个字符不是任何

2018今日头条春招的一道笔试题 —— 通过改变枚举的变量进行枚举优化

题目如下: 这道题我们最先想到的做法,应该就是2重循环枚举数对,然后把数对放在set里去重,最后输出set的大小,即输出set.size( ).代码如下: 1 #include<iostream> 2 #include<set> 3 using namespace std; 4 5 int n, k, a[100000]; 6 set<pair<int, int>> mypairs; 7 8 int main() 9 { 10 cin >> n

【转】嵌入式软件工程师经典笔试题

嵌入式软件工程师经典笔试题 > 预处理器(Preprocessor) 1. 用预处理指令#define 声明一个常数,用以表明1年中有多少秒(忽略闰年问题) #define SECONDS_PER_YEAR (60 * 60 * 24 * 365)UL 我在这想看到几件事情: 1). #define 语法的基本知识(例如:不能以分号结束,括号的使用,等等) 2). 懂得预处理器将为你计算常数表达式的值,因此,直接写出你是如何计算一年中 有多少秒而不是计算出实际的值,是更清晰而没有代价的. 3).

Java开发工程师上机笔试题

网上看到3道比较好的Java开发工程师上机笔试题,没有答案这里把答案写出来,给大家参考. 1.编一个程序,输入10个整数,并放在数组中,先降序输出所有的数,再统计并输出其中正数.负数和零的个数 package cn.Pigzhu.test; import java.util.Scanner; /**  * 控制台输入10个数字,并输入正负和零的个数  * @author xiaoyezhu  *  */ public class test { public static void main(St

转:嵌入式软件工程师经典笔试题

> 预处理器(Preprocessor) 1. 用预处理指令#define 声明一个常数,用以表明1年中有多少秒(忽略闰年问题)  #define SECONDS_PER_YEAR (60 * 60 * 24 * 365)UL 我在这想看到几件事情: 1). #define 语法的基本知识(例如:不能以分号结束,括号的使用,等等) 2). 懂得预处理器将为你计算常数表达式的值,因此,直接写出你是如何计算一年中有多少秒而不是计算出实际的值,是更清晰而没有代价的. 3). 意识到这个表达式将使一个1

【美团点评】2020校招算法工程师方向笔试题

这套题难啊..好多坑点.而且想了好久.交卷两小时..想了一晚上. 第一题还是不知道怎么dp的..可能要坑一下明天补.. 如果有大佬能指点下我就更好了QAQ.我是真的菜.. 试题链接:2020校招算法工程师方向笔试题 5. 外卖小哥的保温箱 题意:众所周知,美团外卖的口号是:”美团外卖,送啥都快”.身着黄色工作服的骑手作为外卖业务中商家和客户的重要纽带,在工作中,以快速送餐突出业务能力:工作之余,他们会通过玩智力游戏消遣闲暇时光,以反应速度彰显智慧,每位骑手拿出装有货物的保温箱,参赛选手需在最短的

0810------笔试题----------腾讯2012年的一道笔试题

1.题目要求 a)b[i] = a[0] *a[1] *a[2]*….a[n-1]/ a[i],求出数组b: b)要求不能用除法,除循环控制变量以外,不许额外申请其余变量,时间复杂度为O(n),空间复杂度为O(1). 2.程序思路 a)假设 N = 5,那么 b[0] =      a[1]*a[2]*a[3]*a[4];            b[1] = a[0]*     a[2]*a[3]*a[4];            b[2] = a[0]*a[1]*     a[3]*a[4];