笔试算法题(14):整数二进制表示中的1 & 判定栈的push和pop序列是否对应

出题:输入一个整数,要求计算此整数的二进制表示中1的个数

分析:

  • 如果整数表示为k,当其是负数的时候,使用1<<i分别检测k的每一位;当其位整数的时候,则k/2表示将其二进制表示右移一位,k%2
    ==0表示其是否是偶数,如果不是则说明当前二进制表示的最右边一位为1,当k==0成立的时候移位结束;

  • 另外还可以使用‘消1’的方法,如果二进制表示A为‘****1000‘,则A-1为‘****0111‘,也就是我们仅关注二进制表示最右边的第一个
    1,这样的话A&(A-1)的结果就可以将最右边的第一个1开始往右边的所有位都清除为0,‘****0000‘;所以没进行一次处理就消除一个
    1,直到整个数字为0,则A&(A-1)进行的次数就是1的个数;

  • 另外可以使用空间换时间的策略,将int所有取值所对应的1的个数存储为一个数组,则直接取数组值就可以得到;

解题:


 1 int count1Binary(int k) {
2 int count=0;
3 if(k<0) {
4 /**
5 * 针对负数的情况,使用1<<i可以每次检测k的一个
6 * 位上是否为1,移动次数为sizeof(int),也可以
7 * 使用while(i){………, i=i<<1}这样当1溢出的时候
8 * 就是0,也就是结束的时候
9 * */
10 int limit=sizeof(int)*8;
11 printf("the size of int is: %d",limit);
12 for(int i=0;i<limit;i++) {
13 if((k & (1 << i)) != 0) count++;
14 }
15 }
16 while(k>0) {
17 /**
18 * 此判断条件可以替换为 k&1 == 1
19 * */
20 if(k%2 == 1) {
21 count++;
22 }
23 /**
24 * 移位操作可以替换为 k>>1
25 * 可以获得更高运算效率
26 * */
27 k/=2;
28 }
29
30 return count;
31 }
32
33 int count1Binary2(int k) {
34 int count=0;
35 while(k) {
36 k=k&(k-1);
37 count++;
38 }
39 return count;
40 }
41
42 int main() {
43 printf("\n%d\n", count1Binary(-23));
44 printf("\n%d\n", count1Binary2(-23));
45 return 0;
46 }

出题:判断stack的push和pop序列是否对应,push和pop可能交替发生

分析:例如:push序列"1,2,3,4,5",pop序列"4,5,3,2,1"

解题:


 1 /**
2 * 由于当前pop出去的元素肯定位于堆栈的栈顶,所以可以根据
3 * 这个性质,用push中的元素重建堆栈,创建tempStack,则
4 * 当前pop出去的元素要么已经位于tempStack的栈顶,要么还
5 * 在push序列中,如果是后者则需要将对应元素之前的元素都压入
6 * tempStack。所以如果上述两种情况都没有发生,则失败;如果
7 * 最终的pop序列和push序列都遍历完全,tempStack非空,则返
8 * 回true,否则返回失败。
9 * */
10 bool judgePushPopSeq(int *push, int pushL, int *pop, int popL) {
11 MyStack *tempStack=new MyStack();
12 int pushI=0, popI=0;
13 int temp;bool isFound;
14 while(true) {
15 isFound=false;
16 if(tempStack->peek(&temp) && temp==pop[popI]) {
17 isFound=true;
18 tempStack->pop(NULL);
19 popI++;
20 } else {
21 for(int i=pushI;i<pushL;i++) {
22 if(push[i] == pop[popI]) {
23 for(int j=pushI;j<i;j++) {
24 tempStack->push(push[j]);
25 }
26 pushI=i++;
27 popI++;
28 isFound=true;
29 break;
30 }
31 }
32 }
33 if(!isFound) {
34 delete tempStack;
35 return false;
36 }
37 if(popI==popL && pushI==pushL && tempStack->isEmpty()) {
38 delete tempStack;
39 return true;
40 } else {
41 delete tempStack;
42 return false;
43 }
44 }
45 }

时间: 2024-10-07 09:06:15

笔试算法题(14):整数二进制表示中的1 & 判定栈的push和pop序列是否对应的相关文章

每天一道算法题:数字二进制形式中1的个数

题目:请实现一个函数,属于一个整数,输出该数二进制表示中1的个数,例如把9表示成二进制是1001,有2位为1.因此如果输入9,该函数输出2. 可能的死循环陷阱 看完题目,相信大家很快就能想到一个解题思路:先判断整数二进制表示中最右边的一位是否为1,接着把输入的整数右移一位,此时原来处于从右边起的第二位被移动至最右边了,再判断是不是1,这样每次移动一位,直到这个整数变成0,即能够得到整数二进制表示形式中1的个数,而现在问题变为如何判断数字的最后一位为1,其实这个也很简单,只需要将数字与1做与运算,

笔试算法题

转自:http://www.cnblogs.com/xwdreamer/archive/2011/12/13/2296910.html 1.把二元查找树转变成排序的双向链表 题目:输入一棵二元查找树,将该二元查找树转换成一个排序的双向链表.要求不能创建任何新的结点,只调整指针的指向.   10  / \  6  14 / \ / \4  8 12 16 转换成双向链表4=6=8=10=12=14=16.  首先我们定义的二元查找树 节点的数据结构如下: struct BSTreeNode{  i

笔试算法题(34):从数字序列中寻找仅出现一次的数字 &amp; 最大公约数(GCD)问题

出题:给定一个数字序列,其中每个数字最多出现两次,只有一个数字仅出现了一次,如何快速找出其中仅出现了一次的数字: 分析: 由于知道一个数字异或操作它本身(X^X=0)都为0,而任何数字异或操作0都为它本身,所以当所有的数字序列都异或操作之后,所有出现两次的数字异或操作之后的结果都为0,则最后剩下的结果就是那个仅出现了一次的数字: 如果有多个数字都仅仅出现了一次,则上述的异或操作方法不再适用:如果确定只有两个数字只出现了一次,则可以利用X+Y=a和XY=b求解: 解题: 1 int findSin

笔试算法题(23):数值整数次方 &amp; 最大对称子串

出题:数值的整数次方(不考虑溢出),实现函数double Power(double base, int exponent): 分析: 解法1:最简单的方法是使用直接的乘法运算,但是注意处理几种特殊情况:exponent为负数,base为0: 解法2:将exponent分解成2的不同次方相加的表达式,通过重复平方来最大程度的减少乘法运算的次数. 当然,也可以递归实现,当n为偶数时,a^n=a^(n/2) * a^(n/2):当n为奇数时,a^n=a^((n-1)/2) * a^((n-1)/2)

笔试算法题(54):快速排序实现之三路划分, 三元中值法和插入排序处理小子文件

议题:快速排序算法实现之三(三路划分遍历,解决与划分元素相等元素的问题) 分析: 算法原理:使用三路划分策略对数组进行划分(也就是荷兰国旗问题,dutch national flag problem).这个实现是对实现二的改进,它添加处理等于划分元素的值的逻辑,将所有等于划分元素的值集中在一起,并且以后都不会再对他们进行划分. 本算法中使用四个标示值进行操作.使用left和right同时向中间遍历时,当left遇见等于划分元素时,就与iflag指向的值进行交换 (iflag指向的当前值到最左端表

笔试算法题(07):还原后序遍历数组 &amp; 半翻转英文句段

出题:输入一个整数数组,判断该数组是否符合一个二元查找树的后序遍历(给定整数数组,判定其是否满足某二元查找树的后序遍历): 分析:利用后序遍历对应到二元查找树的性质(序列最后一个元素必定是根节点,从左向右第一个比根节点大的元素开始直到根节点之前的所有元素必定在右子树,之前的所有元素必定在左子树): 解题: 1 bool PostOrderCheck(int *array, int i, int j) { 2 /** 3 * 如快速排序一样,解决小子文件 4 * */ 5 if(j-i+1 ==

笔试算法题(06):最大连续子数组和 &amp; 二叉树路径和值

出题:预先输入一个整型数组,数组中有正数也有负数:数组中连续一个或者多个整数组成一个子数组,每个子数组有一个和:求所有子数组中和的最大值,要求时间复杂度O(n): 分析: 时间复杂度为线性表明只允许一遍扫描,当然如果最终的最大值为0表明所有元素都是负数,可以用线性时间O(N)查找最大的元素.具体算法策略请见代码和注释: 子数组的起始元素肯定是非负数,如果添加的元素为正数则记录最大和值并且继续添加:如果添加的元素为负数,则判断新的和是否大于0,如果小于0则以下一个元素作为起始元素重新开始,如果大于

笔试算法题(20):寻找丑数 &amp; 打印1到N位的所有的数

出题:将只包含2,3,5的因子的数称为丑数(Ugly Number),要求找到前面1500个丑数: 分析: 解法1:依次判断从1开始的每一个整数,2,3,5是因子则整数必须可以被他们其中的一个整除,如果不包含任何其他因子则最终的结果为1: 解法2:小丑数必然是某个大丑数的因子,也就是乘以2,3,或者5之后的值,所以可以利用已经找到的丑数来寻找下一个丑数,使用数组有序保存已经找到的丑 数,并且当前最大丑数值为M:用大于M/2的丑数乘以2得到M1,用大于M/3的丑数乘以3得到M2,用大于M/5的丑数

笔试算法题(43):布隆过滤器(Bloom Filter)

议题:布隆过滤器(Bloom Filter) 分析: BF由一个很长的二进制向量和一系列随机映射的函数组成,通过多个Hash函数将一个元素映射到一个Bit Array中的多个点,查询的时候仅当所有的映射点都为1才能判断元素存在于集合内:BF用于检索一个元素是否在一个集合中,记忆集合求交集:优点是空间 和时间效率都超过一般查询算法,缺点是有一定的误判概率和删除困难: 如下图,使用三个哈希函数对每个元素进行映射,这样每个元素对应HashTable中的三个位置,如果查找w是否在HashTable中则仍