以技术为主
编程语言与算法设计
关于const与volatile笔试题目的分析
十 17th
昨天笔试遇到了关于c++中关于const与const_cast的题目,大概如下:
int main(int argc, char* argv[]) { const int a = 10; int * p = const_cast<int *>(&a); *p = 1; printf("%d %d\n", a, *p); return 0; }
求上述程序的输出结果,正确答案是:10 1
分析如下:
首先可以确定是p和&a的地址是指向同一片内存区域的,理论上来说最后的输出结果应该是1 1
但是为什么会输出a的值为10呢? 猜测应该是const关键字的问题,可能编译器看到a为const型变量,所以在编译期就将所有的a直接替换为10了,这个是编译器做的一个优化,
下面简单的验证下:
直接使用下面的命令来看下编译后的汇编代码,关键部分的汇编如下:
movl %edi, -20(%rbp) movq %rsi, -32(%rbp) movl $10, -12(%rbp) leaq -12(%rbp), %rax movq %rax, -8(%rbp) movq -8(%rbp), %rax movl $1, (%rax) movq -8(%rbp), %rax movl (%rax), %edx movl $10, %esi movl $.LC0, %edi movl $0, %eax call printf movl $0, %eax leave ret
显然%rax中存放的指针p的值,(%rax)代表间接寻址
在调用printf函数之前,将10放入%esi, (%rax)放入到%edx中,显然验证了上述的猜想
关于volatile关键字
如何避免编译器做这方面的优化呢?
一个常用的方法是将变量a加上关键字volatile,代表是”易变,每次都需要从内存中读取,这样上述程序的运行结果就是1 1了
当然修改常量变量的值不是好的编程习惯,尽量还是少用上述用法
register、volatile、restrict 三关键字的用法[转载]
十 6th
原文地址:register、volatile、restrict 三关键字的用法 – RaymondAmos的技术专栏 – CSDN博客.
register
使用修饰符register声明的变量属于寄存器存储类型。该类型与自动存储类型相似,具有自动存储时期、代码块作用域和内连接。声明为register 仅仅是一个请求,因此该变量仍然可能是普通的自动变量。无论哪种情况,用register修饰的变量都无法获取地址。如果没有被初始化,它的值是未定的。
volatile
volatile告诉编译器该被变量除了可被程序修改外,还可能被其他代理、线程修改。因此,当使用volatile 声明的变量的值的时候,系统总是重新从它所在的内存读取数据,而不使用寄存器中的缓存的值。比如,
val1=x; val2=x;
如 果没有声明volatile,系统在给val2赋值的时候可能直接从寄存器读取x,而不是从内存的初始位置读取。那么在两次赋值之间,x完全有可能被被某 些编译器未知的因素更改(比如:操作系统、硬件或者其它线程等)。如果声明为volatile,编译器将不使用缓存,而是每次都从内存重新读取x。
restrict
restrict是c99引入的,它只可以用于限定指针,并表明指针是访问一个数据对象的唯一且初始的方式,考虑下面的例子:
int ar[10]; int * restrict restar=(int *)malloc(10*sizeof(int)); int *par=ar;
这里说明restar是访问由malloc()分配的内存的唯一且初始的方式。par就不是了。那么:
for(n=0;n<10;n++) { par[n]+=5; restar[n]+=5; ar[n]*=2; par[n]+=3; restar[n]+=3; }
因 为restar是访问分配的内存的唯一且初始的方式,那么编译器可以将上述对restar的操作进行优化:restar[n]+=8;。而par并不是访 问数组ar的唯一方式,因此并不能进行下面的优化:par[n]+=8;。因为在par[n]+=3前,ar[n]*=2进行了改变。使用了关键字 restric,编译器就可以放心地进行优化了。这个关键字据说来源于古老的FORTRAN。
总结
两个关键字:volatile和restrict,两者都是为了方便编译器的优化。
今天EMC笔试题目
九 25th
两道的题目:
1. dup(int fd)和dup2(int fd1, int fd2)函数的区别:详细请见http://blog.donews.com/mutecat/archive/2007/09/20/1212178.aspx
2. 有关一致性哈希的算法设计
其他的是 多项选择题目,涉及的范围比较广,linux和语言层次的题目偏多一些吧
包括堆栈缓冲区溢出以及linux内核中container_of宏的实现,以及spinlock和虚拟内存的相关知识
关于container_of这个请参考我的前一篇blog: http://yaronspace.cn/blog/index.php/archives/1026
[编程之美]随机数范围扩展方法总结
八 3rd
问题描述
已知random3()这个随机数产生器生成[1, 3]范围的随机数,请用random3()构造random5()函数,生成[1, 5]的随机数?
问题分析
如何从[1-3]范围的数构造更大范围的数呢?同时满足这个更大范围的数出现概率是相同的,可以想到的运算包括两种:加法和乘法
考虑下面的表达式:
3 * (random3() – 1) + random3();
可以计算得到上述表达式的范围是[1, 9] 而且数的出现概率是相同的,即1/9
下面考虑如何从[1, 9]范围的数生成[1, 5]的数呢?
可以想到的方法就是 rejection sampling 方法,即生成[1, 9]的随机数,如果数的范围不在[1, 5]内,则重新取样
解决方法
int random5() { int val = 0; do { val = 3 * (random3() - 1) + random3(); } while (val > 5); return val; }
归纳总结
将这个问题进一步抽象,已知random_m()随机数生成器的范围是[1, m] 求random_n()生成[1, n]范围的函数,m < n && n <= m *m
一般解法:
int random_n() { int val = 0 ; int t; // t为n最大倍数,且满足 t <= m * m do { val = m * (random_m() - 1) + random_m(); } while (val > t); return val; }
参考资料:
http://stackoverflow.com/questions/137783/expand-a-random-range-from-1-5-to-1-7
140个Google的面试题【转载】
七 16th
原文地址:http://coolshell.cn/articles/3345.html
来源:http://blog.seattleinterviewcoach.com/2009/02/140-google-interview-questions.html(墙)

- Product Marketing Manager
- Product Manager
- Software Engineer
- Software Engineer in Test
- Quantitative Compensation Analyst
- Engineering Manager
- AdWords Associate
这篇Blog例举了Google用来面试下面这几个职位的面试题。很多不是很容易回答,不过都比较经典与变态,是 Google,Microsoft,Amazon之类的公司的风格。对于本文,我没有翻译,因为我相信,英文问题是最好的。不过对于有些问题,我做了一些 注释,不一定对,但希望对你有帮助启发。对于一些问题,如果你百思不得其解,可以Google一下,StackOverflow或是Wikipedia上 可能会给你非常全面的答案。
- Why do you want to join Google?
- What do you know about Google’s product and technology?
- If you are Product Manager for Google’s Adwords, how do you plan to market this?
- What would you say during an AdWords or AdSense product seminar?
- Who are Google’s competitors, and how does Google compete with them?
- Have you ever used Google’s products? Gmail?
- What’s a creative way of marketing Google’s brand name and product?
- If you are the product marketing manager for Google’s Gmail product, how do you plan to market it so as to achieve 100 million customers in 6 months?
- How much money you think Google makes daily from Gmail ads?
- Name a piece of technology you’ve read about recently. Now tell me your own creative execution for an ad for that product.
- Say an advertiser makes $0.10 every time someone clicks on their ad. Only 20% of people who visit the site click on their ad. How many people need to visit the site for the advertiser to make $20?
- Estimate the number of students who are college seniors, attend four-year schools, and graduate with a job in the United States every year.
- How would you boost the GMail subscription base?
- What is the most efficient way to sort a million integers? (陈皓:merge sort)
- How would you re-position Google’s offerings to counteract competitive threats from Microsoft?
- How many golf balls can fit in a school bus? (陈皓:这种题一般来说是考你的解题思路的,注意,你不能单纯地把高尔夫球当成一个小立方体,其是一个圆球,堆起来的时候应该是错开的——也就是三个相邻 的球的圆心是个等边三角形)
- You are shrunk to the height of a nickel and your mass is proportionally reduced so as to maintain your original density. You are then thrown into an empty glass blender. The blades will start moving in 60 seconds. What do you do?
- How much should you charge to wash all the windows in Seattle?
- How would you find out if a machine’s stack grows up or down in memory?
- Explain a database in three sentences to your eight-year-old nephew. (陈皓:用三句话向8岁的侄子解释什么是数据库,考你的表达能力了)
- How many times a day does a clock’s hands overlap?(陈皓:经典的时钟问题)
- You have to get from point A to point B. You don’t know if you can get there. What would you do?
- Imagine you have a closet full of shirts. It’s very hard to find a shirt. So what can you do to organize your shirts for easy retrieval? (陈皓:很不错的一道题,不要以为分类查询很容易,想想图书馆图书的分类查询问题吧。另外,你处想想如何在你在你的衣柜里实现一个相当于Hash表或是一 个Tree之类的数据结构)
- Every man in a village of 100 married couples has cheated on his wife. Every wife in the village instantly knows when a man other than her husband has cheated, but does not know when her own husband has. The village has a law that does not allow for adultery. Any wife who can prove that her husband is unfaithful must kill him that very day. The women of the village would never disobey this law. One day, the queen of the village visits and announces that at least one husband has been unfaithful. What happens? (陈皓:这个问题很有限制级,哈哈,非常搞的一个问题,注意wife们的递归,这类的问题是经典的分布式通讯问题,上网搜 一搜吧。)
- In a country in which people only want boys, every family continues to have children until they have a boy. If they have a girl, they have another child. If they have a boy, they stop. What is the proportion of boys to girls in the country?(陈皓:第一反应是——这个国家是中国。一个概率问题,其实,无论你怎么生,50%的概率是永远不变的。)
- If the probability of observing a car in 30 minutes on a highway is 0.95, what is the probability of observing a car in 10 minutes (assuming constant default probability)?
- If you look at a clock and the time is 3:15, what is the angle between the hour and the minute hands? (The answer to this is not zero!)
- Four people need to cross a rickety rope bridge to get back to their camp at night. Unfortunately, they only have one flashlight and it only has enough light left for seventeen minutes. The bridge is too dangerous to cross without a flashlight, and it’s only strong enough to support two people at any given time. Each of the campers walks at a different speed. One can cross the bridge in 1 minute, another in 2 minutes, the third in 5 minutes, and the slow poke takes 10 minutes to cross. How do the campers make it across in 17 minutes?(陈皓:经典的过桥问题)
- You are at a party with a friend and 10 people are present including you and the friend. your friend makes you a wager that for every person you find that has the same birthday as you, you get $1; for every person he finds that does not have the same birthday as you, he gets $2. would you accept the wager?
- How many piano tuners are there in the entire world?
- You have eight balls all of the same size. 7 of them weigh the same, and one of them weighs slightly more. How can you find the ball that is heavier by using a balance and only two weighings?(陈皓:经典的称重问题。这样的问题花样很多,不过都不难回答)
- You have five pirates, ranked from 5 to 1 in descending order. The top pirate has the right to propose how 100 gold coins should be divided among them. But the others get to vote on his plan, and if fewer than half agree with him, he gets killed. How should he allocate the gold in order to maximize his share but live to enjoy it? (Hint: One pirate ends up with 98 percent of the gold.)
- You are given 2 eggs. You have access to a 100-story building. Eggs can be very hard or very fragile means it may break if dropped from the first floor or may not even break if dropped from 100th floor. Both eggs are identical. You need to figure out the highest floor of a 100-story building an egg can be dropped without breaking. The question is how many drops you need to make. You are allowed to break 2 eggs in the process. (陈皓:从3的倍数的楼层开始扔,比如3,6,9,12…..,如果鸡蛋在3n层碎了,那到在3n-1层扔第二个鸡蛋,如果没碎,则最高不碎楼层为3n- 1,否则为3n-2)
- Describe a technical problem you had and how you solved it.
- How would you design a simple search engine?
- Design an evacuation plan for San Francisco.
- There’s a latency problem in South Africa. Diagnose it. (陈皓:这个问题完全是在考你的解决问题的能力。没有明确的答案。不过,解决性能问题的第一步通常是找出瓶颈,找瓶颈有很多种方法,工具,二分查,时间记 录等等。)
- What are three long term challenges facing Google?
- Name three non-Google websites that you visit often and like. What do you like about the user interface and design? Choose one of the three sites and comment on what new feature or project you would work on. How would you design it?
- If there is only one elevator in the building, how would you change the design? How about if there are only two elevators in the building? (陈皓:经典的电梯设计问题,这种问题千变万化,主要是考你的设计能力和需求变化的适变能力,与此相似的是酒店订房系统。)
- How many vacuum’s are made per year in USA?
[编程之美]N个鸡蛋放到M个篮子的方法
七 5th
今天看到一个面试题目,题目大意:将n个鸡蛋放到m个篮子,同时保证不能有空篮子,且对于任意小于等于n的数,都能保证有几个篮子的鸡蛋数等于这个数
题目分析
第一眼看到这个题目时,感觉像是整数拆分问题,但是有两个限制:1. 不能有空篮子 2.保证能够针对任意<=n的数,都可以用几个篮子的鸡蛋的和来表示,所以应该不是整数拆分问题。
首先想到是就是穷举,也就是深度搜索,但是如何判断搜索的一个结果是否满足第二个条件呢?
这里可以通过归纳的方法,假设当前的前n个数为Sn,同时任意<=Sn的数都可以用前n个数某些数的和来表示,那么第n+1个数的范围是什么呢?
这里应该可以想到,如果第n+1个数>(Sn) + 1 的话,相当于有间隔,那么(Sn) + 1这个就无法表示,所以第n+1个数应该是<= Sn + 1,这样就可以满足
任意的<=S(n+1) 的数都可以用前n+1个数来表示;
同时在搜索的过程中保证序列是非降序的,而且会有剪枝的方法,实现具体看代码
代码实现
使用mmap实现文件的拷贝
七 4th
今天看csapp看到了虚拟存储器的映射以及mmap函数的用法,作为练习,使用mmap来实现文件的拷贝操作,同时与传统的文件拷贝操作进行了性能比较。
mmap与munmap函数介绍:
#include <unistd .h> #include <sys /mman.h> void *mmap(void *start, size_t length, int prot, int flag, int fd, off_t offset); //返回:若成功时则返回映射区域的指针,若出错则为MAP_FAILED(-1) </sys></unistd>
start: 最好从start开始的一个区域,这个是hint,具体映射结果还是要看返回结果
length: 映射区域的大小
prot: 映射区域的访问权限位 PROT_EXEC PROT_READ PROT_WRITE PROT_NONE
flags: 映射对象的类型 MAP_ANON MAP_PRIVATE MAP_SHARED
munmap函数删除映射区域
#include <unistd .h> #include <sys /mman.h> int munmap(void *start, size_t length); </sys></unistd>
实验
分别使用了mmap函数和普通的read write实现了文件的复制拷贝,下面是通过复制50M的文件性能分析:
[yangguang@sim124 ~]$ time ./workspace/mmapcopy linux-20101214.tar.gz ./output real 0m0.100s user 0m0.034s sys 0m0.065s
[yangguang@sim124 ~]$ time ./workspace/copy linux-20101214.tar.gz ./output real 0m5.016s user 0m0.000s sys 0m0.124s
可以看到使用mmap的性能明显高于使用Read write的方式,这里主要原因是使用mmap减少了用户态和内核态间数据
的拷贝
更多 >
[编程之美]使用最大堆和最小堆来求中位数
六 28th
好久没更新blog,都快荒废了,今天发个算法问题
题目介绍:
输入为不断地数字流,实时显示出当前已经输入的数字序列的中位数
解答:
求中位数的方法很多,对于大数据量最经典是桶的计数方法,但是对于这个问题不适用,因为数据是不断变化的
可以用最大堆和最小堆来解答这个问题:
1.假设当前的中位数为m,其中最大堆维护的是<=m的数字序列,最小堆维护的是>=m的数字序列,但是两个堆都不包含m
2.当新的数字到达时,比如为a,将a与m进行比较,若a<=m 则将其加入到最大堆中,否则将其加入到最小堆中
3.如果此时最小堆和最大堆的元素个数的差值>=2 ,则将m加入到元素个数少的堆中,然后从元素个数多的堆将根节点赋值到m,最后重建两个最大堆和最小堆,返回到2
【编程之美】单链表是否存在环以及环入口的位置【转载】
五 26th
原文地址:http://blog.csdn.net/ssfp8762/archive/2009/07/08/4331419.aspx
解答:
一、判断链表是否存在环,办法为:
设置两个指针(fast, slow),初始值都指向头,slow每次前进一步,fast每次前进二步,如果链表存在环,则fast必定先进入环,而slow后进入环,两个指针必定相遇。
二、链表环入口的位置计算
当fast若与slow相遇时,slow肯定没有走遍历完链表,而fast已经在环内循环了n圈(1<=n)。假设slow走了s步,则fast走了2s步(fast步数还等于s 加上在环上多转的n圈),设环长为r,则:
2s = s + nr
s= nr
设整个链表长L,入口环与相遇点距离为x,起点到环入口点的距离为a。
a + x = nr
a + x = (n – 1)r +r = (n-1)r + L – a
a = (n-1)r + (L – a – x)
(L – a – x)为相遇点到环入口点的距离,由此可知,从链表头到环入口点等于(n-1)循环内环+相遇点到环入口点,于是我们从链表头、与相遇点分别设一个指针,每次各走一步,两个指针必定相遇,且相遇第一点为环入口点。
扩展问题:
判断两个单链表是否相交,如果相交,给出相交的第一个点(两个链表都不存在环)。
比较好的方法有两个:
一、将其中一个链表首尾相连,检测另外一个链表是否存在环,如果存在,则两个链表相交,而检测出来的依赖环入口即为相交的第一个点。
二、如果两个链表相交,那个两个链表从相交点到链表结束都是相同的节点,我们可以先遍历一个链表,直到尾部,再遍历另外一个链表,如果也可以走到同样的结尾点,则两个链表相交。
这时我们记下两个链表length,再遍历一次,长链表节点先出发前进(lengthMax-lengthMin)步,之后两个链表同时前进,每次一步,相遇的第一点即为两个链表相交的第一个点。
平面中两点的最近距离与最远距离
五 23rd
今天看编程之美,看到求平面中两点的最近距离,书中给出了O(nlogn)算法,主要是采用分治的方法来做的,首先将平面的点按x坐标分为两部分,分别求最近点对,然后是合并;合并过程中对于两个点分别在两个区域的分析非常巧妙,有效地减少了需要比较的点对的个数。
在poj中对应的题目3714
然后又看到了扩展问题:如何求平面中最远的两个点的距离
这个就不能继续套用“最近距离点对”的分治策略,上网查了下,原来是使用凸包算法+旋转卡壳算法,poj中对应的题目是2187和3608
这里简单记录下,明天做下这两个题目
关于凸包算法和旋转卡壳算法的介绍:
http://yishan.cc/blogs/gpww/archive/2011/02/16/graham-s-scan.aspx
http://www.cppblog.com/staryjy/archive/2010/09/25/101412.html
http://yishan.cc/blogs/gpww/archive/2011/02/15/1787.aspx
近期评论