标签

显示标签为“Interview Questions”的博文。显示所有博文
显示标签为“Interview Questions”的博文。显示所有博文

2011年3月22日星期二

Quick Sort 快排

void quickSort(int* a, int start, int end)
{
    if(start == end)
        return;
    int key = a[start];
    int keyIndex = start;
    int i = start, j = end;
    int backward = 1;
    int temp;
    while(i != j)
    {
        if(backward)
        {
            for(; j > i; j--)
            {
                if(a[j] < key)
                {
                    temp = a[j];
                    a[j] = a[i];      //a[i]  == key
                    a[i] = temp;
                    keyIndex = j;
                    break;
                }
            }
            backward = 0;
        }
        else
        {
            for(; i < j; i++)
            {
                if(a[i] > key)
                {
                    temp = a[j];       //a[j]  == key
                    a[j] = a[i];
                    a[i] = temp;
                    keyIndex = i;
                    break;
                }
            }
            backward = 1;
        }
    }
    quickSort(a, start, keyIndex);
    if(keyIndex != end)
        quickSort(a, keyIndex + 1, end);
}

2011年2月19日星期六

Microsoft面试智力题

1.你让工人为你工作7天,给工人的回报是一根金条。金条平分成相连的7段 ,你必须在每天结束时给他们一段金条,如果只许你两次把金条弄断,你如何给你的工人付费?
将金条切成1,2,4
day1:给1
day2:给2,工人归回1

day3:给1
day4:给4,工人归还1,2
day5:给1
day6:给2,工人归回1
day7:给1

2. 请把一盒蛋糕切成8份,分给8个人,但蛋糕盒里还必须留有一份。
把切成的8份蛋糕先拿出7份分给7人,剩下的1份连蛋糕盒一起分给第8个人。

3.小明一家过一座桥,过桥时是黑夜,所以必须有灯。现在小明过桥要1秒,小明的弟弟要3秒,小明的爸爸要6秒,小明的妈妈要8秒,小明的爷爷要12秒。每次此桥最多可过两人,而过桥的速度依过桥最慢者而定,而且灯在点燃后30秒就会熄灭。问:小明一家如何过桥?
1. 小明与弟弟过桥,小明回来,耗时4秒;
2. 小明与爸爸过河,弟弟回来,耗时9秒;
3. 妈妈与爷爷过河,小明回来,耗时13秒;
4. 小明与弟弟过河,耗时3秒,总共耗时29秒

4.一群人开舞会,每人头上都戴着一顶帽子。帽子只有黑白两种,黑的至少有一顶。每个人都能看到其他人帽子的颜色,却看不到自己的。主持人先让大家看看别人头上戴的是什么帽子,然后关灯,如果有人认为自己戴的是黑帽子,就打自己一个耳光。第一次关灯,没有声音。于是再开灯,大家再看一遍,关灯时仍然鸦雀无声。一直到第三次关灯,才有劈劈啪啪打耳光的声音响起。问有多少人戴着黑帽子?
假如只有一个人戴黑帽子,那他看到所有人都戴白帽,在第一次关灯时就应自打耳光,所以应该不止一个人戴黑帽子;如果有两顶黑帽子,第一次两人都只看到对方头上的黑帽子,不敢确定自己的颜色,但到第二次关灯,这两人应该明白,如果自己戴着白帽,那对方早在上一次就应打耳光了,因此自己戴的也是黑帽子,于是也会有耳光声响起;可事实是第三次才响起了耳光声,说明全场不止两顶黑帽,依此类推,应该是关了几次灯,有几顶黑帽。

5. 烧一根不均匀的绳要用一个小时,如何用它来判断半个小时?如果有两根这样的绳子,如何判断45分钟。
1. 两边一起烧。烧绳子可理解为在单位时间内烧掉的绳子体积是一定的。两头点可理解为燃烧速度增加一倍,自然时间是原来的1/2。
2. 同时点燃其中一根绳子的两头和另一条绳子的一头。第一条燃尽的时候过去了半个小时。同时第二条绳子还能烧半个小时。此时马上点燃第二条绳子的另一头。燃尽时间为15分钟。相加为45分钟。
6. 有一辆火车以每小时15公里的速度离开洛杉矶直奔纽约,另一辆火车以每小时20公里的速度从纽约开往洛杉矶。如果有一只鸟,以外30公里每小时的速度和两辆火车现时启动,从洛杉矶出发,碰到另辆车后返回,依次在两辆火车来回的飞行,直道两面辆火车相遇,请问,这只小鸟飞行了多长距离?
假设洛杉矶到纽约的距离为s
那小鸟飞行的距离就是(s/(15+20))*30。


7. U2合唱团在17分钟内得赶到演唱会场,途中必需跨过一座桥,四个人从桥的同一端出发,你得帮助他们到达另一端,天色很暗,而他们只有一只手电筒。一次同时最多可以有两人一起过桥,而过桥的时候必须持有手电筒,所以就得有人把手电筒带来带去,来回桥两端。手电筒是不能用丢的方式来传递的。四个人的步行速度各不同,若两人同行则以较慢者的速度为准。Bono需花1分钟过桥,Edge需花2分钟过桥,Adam需花5分钟过桥,Larry需花10分钟过桥。他们要如何在17分钟内过桥呢?
1. 1和2过,1回,耗时3
2. 5和10过,2回,耗时12
3. 1和2过,耗时2。
总耗时17

8. 有7克、2克砝码各一个,天平一只,如何只用这些物品三次将140克的盐分成50、90克各一份?
方法1:
1. 在天平一端2克砝码,将140克盐分成69和71克
2. 在天平一端7克砝码,将69克盐分成31克和38克
3.不放砝码,将38课盐平分
31+19 = 50 

方法2
1. 先把2克和7克法码放一边,称出9克盐
2. 再把7克法码和9克盐放在一起,称出16克的盐
3. 再把9克盐和16克的盐放在左边,右边再称出25克盐
9+16+25 = 50


9. 你有四个装药丸的罐子,每个药丸都有一定的重量,被污染的药丸是没被污染的重量+1.只称量一次,如何判断哪个罐子的药被污染了
1号罐取1个,2号罐取2个,3号罐取3个,4号罐取4个,称量该10个药丸,比正常重量重几就是几号罐的药有问题。

10. 如果你有无穷多的水,一个3夸脱的和一个5夸脱的提桶,你如何准确称出4夸脱的水?
方法1
1. 加满3,倒入5
2. 加满3,倒入5直至其满,则3中剩1
3. 清空5,将3中的1倒入5
4. 加满3,倒入5,则5中为4

方法2
1. 加满5,倒入3加满
2. 清空3,将5中剩余的2倒入3
3. 加满5,倒入3加满,5中剩余的则为4

11. 你有一桶果冻,其中有黄色,绿色,红色三种,,闭上眼睛选出同样颜色的两个,抓取同种颜色的两个。抓取多少个就可以确定你肯定有两个同一颜色的果冻?
4个

12. 对一批编号为1~100 全部开关朝上开的灯进行以下操作
凡是1 的倍数反方向拨一次开关2 的倍数反方向又拨一次开关3 的倍数反方向
又拨一次开关。问最后为关熄状态的灯的编号。

就某个亮着的灯而言,如果拨其开关的次数是奇数次,那么,结果它一定是关着的。根据题意可知,号码为N的灯,拨开关的次数等于N的约数(divisor)的个数,约数个数是奇数,则N一定是平方数。因为10的平方等于100,可知100以内共有10个平方数,即,最后关熄状态的灯共有10盏,编号为1、4、9、16、25、36、49、64、81、100。

13. 假设一张圆盘像唱机上的唱盘那样转动。这张盘一半是黑色,一半是白色
。假设你有数量不限的一些颜色传感器。要想确定圆盘转动的方向,你需要在它周
围摆多少个颜色传感器?它们应该被摆放在什么位置?

两个。可随意摆放,只要不同时放在圆的同一条直径上。根据变色顺序判断。

14. 假设时钟到了12点。注意时针和分针重叠在一起。在一天之中,时针和分
针共重叠多少次?你知道它们重叠时的具体时间吗?

23或22次(依据算不算24小时候的的12点整)。首先,将12小时划分成12个区间,[12, 1), [1,2)...[11, 12]。每个区间中都有一次相遇的时刻,其中在[12, 1)和[11, 12]相遇的时刻都是12点整。那么完成前半天12个小时就相遇了12次。在后12个小时中,由于起始的12点整已经被计算进入前12次中的一次,则后面只有11次相遇。所以总共23次。若不计算最后的那次12点整,则是22次(题目是一天之中,所以这个时候是第二天的开始)。

由于每次相遇到下一次相遇的时间是一定的,我们知道在12个小时内(包括12个小时) 相遇了12次, 又知道第一次和最后一次分别在这个时间段的起始和结束。那么可将这12个小时等分成11段,每一段的长度就是相遇的时间间隔。那么间隔 interval = 60*12 /11 = 720 / 11分钟。
知道间隔时间以后就可以从12点开始每次加上这个间隔时间算出每次相遇的时刻。

另一种方法是解方程。将时钟的一圈分成60个格子,设相遇时分针相对12点的时刻走了x个格子。我们知道分针每走一格,相当于时针走了1/12格。那么可根据指针重合条件列出方程。

假设我们要求[1, 2)区间内的相遇时刻,则有:
x / 12 = x - 5

类似的我们可以求出[2, 3), [3,4)...[11, 12]区间的相遇时刻([0, 1]和[11, 12]的相遇时刻相同):
x / 12 = x - 10,
x / 12 = x - 15
...
x / 12 = x

15. 中间只隔一个数字的两个质数被称为质数对,比如17和19。证明质数对之
间的数字总能被6整除(假设这两个质数都大于6),并证明没有由三个质数组成
的质数对。

大于6的质数(prime number, 合数 composite number都是奇数(只有2是唯一的偶质数)。所以质数对中间的数字一定是偶数,能被2整除(divisible)。由于在大于6的数中,任取三个连续的数字其中有且仅有一个数字能被3整除,而质数对的两个质数肯定不能被3整除(否则不是质数),则中间的那个数必定能被3整除。
一个数既能被2又能被3整除,则它能被6整除。

反证法(Reductio ad absurdum):设x,x+2是一质数对,假设有连续三个质数组成的质数对,则x2+4或者x-2为质数。那么x-2,x和x+2,x+4是可能的两个质数对。则x-1或x+3应能被6整除。但是,由于x+1能被6整除,则x-1和x+3不可能被6整除。所以不存在三个质数组成的质数对。

16. 一个屋子有一个门(门是关闭的)和3盏电灯。屋外有3个开关,分别与这 盏灯相连。你可以随意操纵这些开关,可一旦你将门打开,就不能变换开关了。确定每个开关具体管哪盏灯。
同时开两盏,过一段时间关闭一盏。进门根据灯泡温度决定刚刚关掉的是哪一盏。

17. 假设你有8个球,其中一个略微重一些,但是找出这个球的惟一方法是将两个球放在天平上对比。最少要称多少次才能找出这个较重的球?
2次。
第一次分别取3个求放在天平两端,若不平横则重球在重的一端的三个球中。若不平衡,第二次任取两球放在天平两端,若不平衡则找到重球,若平横则剩下的一球为重球。
若第一次天平平衡。则重求在剩下的2个球中。第二次称量可直接找到重球。

18. 如果你有两个桶,一个装的是红色的颜料,另一个装的是蓝色的颜料。你从蓝色颜料桶里舀一杯,倒入红色颜料桶,再从红色颜料桶里舀一杯倒入蓝颜料桶。两个桶中红蓝颜料的比例哪个更高?通过算术的方式来证明这一点。
设两桶中红蓝颜料都是1。从红桶中舀去1/k。红桶中还有(k - 1)/k的红,蓝桶中有1的蓝和1/k的红。从蓝桶中舀去1/k。此1/k有(1/k) / (1+1/k) * 1 = 1/(k + 1)的蓝,和1/k - 1/k+1 = 1/(k*(k+1)的红。此时红桶中的红是 (k - 1)/k + 1/(k*(k+1) = k/(k + 1)。蓝桶中的蓝是1 - 1/(k + 1) = k/(k+1)。
比例相同。

递归求square root

设要求根的数为n, 定义f(x) = x^2 - n

应用Newton's Method估算 f(x) = 0 的正数解。首先猜测X[0] (X[0] > 0)为方程的解,之后根据recurrence relation: X[i] = X[i-1] - f(X[i-1]) / f''(X[i-1]) = (X[i-1] + n / X[i-1]) / 2 使X[i]不断逼近准确解。 当误差小于一定范围时,返回当前估算值。

double sqrtRecursive(double n, double guess)
{
     if(abs(guess * guess - n) < 0.00001)
         return guess;
     else
         return sqrtRecursive(n, (guess + n/guess)*0.5);
}

2011年2月18日星期五

和为n连续正数序列

题目:输入一个正数n,输出所有和为n连续正数序列。不考虑一个数的序列
例如输入15,由于1+2+3+4+5=4+5+6=7+8=15,所以输出3个连续序列1-54-67-8。 

注意: 由于序列至少有两个元素且连续,所以序列起始元素最大不超过(int)(n/2), 结束元素最大不超过(int)(n/2) + 1, 因此无需遍历 1...n-1。
方法1.
使用枚举的方法,两个for循环可以搞定。时间复杂度O(n^2)

void CountinousSequenceSum_1(int n)
{
    if(n < 3)
        return;

    int sum;

    for(int i = 1; i < n/2 + 1; i++)
    {
        sum = i;
        for(int j = i + 1; j < n/2 + 2; j++)
        {
            sum += j;
            if(sum == n)
            {
                for(int k = i; k < j + 1; k++)
                    cout << k << " ";
                cout << endl;
            }
        }
    }

    return;


方法2.
因为整数序列是有序的,可以设立两个游标small,big,通过判区间[small,big]的和是
否为N来得到这个序列。如果区间和大于n,small往前移动,如果小于 n,big往前移动,等于就输出
这个区间。时间复杂度是0(n)

void CountinousSequenceSum_2(int n)
{
    if(n < 3)
        return;

    int start = 1, end = 2;
    int sum = start + end;
   
    while(end < n/2 + 2)
    {
        if(sum == n)
        {
            for(int i = start; i < end + 1; i++)
                cout << i << " ";
            cout << endl;
            end++;
            sum += end;
        }
        else if(sum > n)
        {
            sum -= start;
            start++;
        }
        else
        {
            sum += end + 1;
            end++;
        }
    }
}


递归法求字符串的全排列 (permutation)

每次递归调用,解决一个当前元素数量为n-k ( k = 0...n-1)的全排列,为解决当前当前排列, 又需要递归解决n-k个元素数量为n-k-1的全排列

举例:字符串abc, n = 3, []中的元素为需要计算排列的元素集,[]外的元素为已经确定排列顺序的元素

                                   [abc]         
     /             |             \
               a[bc]          b[ac]          c[ba]
              /        |         /        \         |        \
  ab[c]   ac[b]   ba[c]   bc[a]  cb[a]   ca[b]
     |            |            |            |            |            |
  abc       acb       bac       bca     cba      cab

第一层:k = 0,1个全排列需解决,为此需解决3个元素数为2的全排列
第二层:k = 1,3个全排列需解决,解决每个全排列需要解决2个元素数为1的全排列
第三层:k = 2,6个全排列需解决,解决每个全排列需要解决2个元素数为0的全排列(说明当前层已解得所需的所有全排列)
第四层:k = 3, k等于n,到达递归底层,打印当前排列

static void RecursivePermute(char* str,int k)//递归函数
{
     int i;
     if(k==strlen(str))
          printf("%s\n",str);
     else
     {
          for(i=k;i<strlen(str);i++)
          {
               ExchangeCharacters(str,k,i);
               RecursivePermute(str,k+1);
               ExchangeCharacters(str,k,i);
          }
     }
}

static void ExchangeCharacters(char* str, int p1,int p2)
{
     char tmp;
     tmp=str[p1];
     str[p1]=str[p2];
     str[p2]=tmp;
}

2011年2月16日星期三

最长公共子序列 (LCS = Longest Common Subsequence) 和最长公共子串 (LCS = Longest Common Substring)

两个序列a,b, L[i][j]为以a[i]和b[j]结尾的最长公共子序列的长度。a长度为m, b长度为n

Longest Common Subsequence (子序列无需连续)

Initial condition:
L[0][j] = (a[0] == b[j]) ? 1 : 0     j = 0...n
L[i][0] = (a[i] == b[0]) ? 1 : 0     i = 0...m
Recurrence relation:
L[i][j] = (a[i] == b[j])  ? L[i-1][j-1] + 1 : max(L[i][j-1], L[i-1][j])    i = 1...m, j = 1...n

最后L[m][n]即为结果

 Longest Common Substring(子串需要连续)

Initial condition:
a[0][j] = (a[0] == b[j]) ? 1 : 0     j = 0...n
a[i][0] = (a[i] == b[0]) ? 1 : 0     i = 0...m
Recurrence relation:
L[i][j] = (a[i] == b[j])  ? L[i-1][j-1] + 1 : 0   i = 1...m, j = 1...n
结果为计算过程中最大的L[i][j] (用一个max变量跟踪)

最长单调递增子序列(LIS)

最长单调递增子 序列,就是在一个数列中最长的按单调递增的顺序排列的序列,该序列在原序列中可以不连续。

解法1:
b[i]为截止到第i个数且以第i个数为结尾的最长单调递增子序列的长度,a为所给序列,则有:
Initial condittion:
b[0]  = 1
Recurrence relation:
b[ i ] = max( a[i] > a[j] ? b[j] + 1 : 1)    j = 0...i-1

//return value: length of LIS
//aMax: LIS array
//a: original array
//b: b[i] stores the length of the local LIS with the last member a[i]
//p: p[i] stores the previous index of member of the local LIS with the last member a[i]

int LIS(int *a, int *b, int *p, int *aMax, int n)
{
    int max = 0;
    int maxIndex;

    for(int i = 0; i < n; i++)
    {
        b[i] = 1;
        for(int j = 0; j < i; j++)
        {
            if(a[i] > a[j] && b[i] < b[j] + 1)
            {
                b[i] = b[j] + 1;
                p[i] = j;
            }
        }

        if(b[i] > max)
        {
            max = b[i];
            maxIndex = i;
        }
    }

    for(int i = max -1; i > -1;  i--)
    {
        aMax[i] = a[maxIndex];
        maxIndex = p[maxIndex];
    }

    return max;
}
复杂度o(n2)

解法2:

将原序列按升序排序,再对原序列和排序后的序列计算LCS(Longest Common Subsequence)的长度。
排序复杂度o(nlogn), LCS复杂度o(n2), 总复杂度o(n2)

最长连续数字序列, 计数并输出

 int longestNumString(char *string, char *output)
{
    int count = 0;
    int max = 0;
    char *start;
    char *startMax;

    while(true)
    {
        if(*string >= '0' && *string <= '9')
            start = string;

        while(*string >= '0' && *string <= '9' && *string)
        {
            string++;
            count++;
        }

        if(count > max)
        {
            max = count;
            startMax = start;
        }

        count = 0;

        if(*string)
            string++;
        else
            break;
    }

    for(int i = 0; i < max; i++)
    {
        *output = *startMax;
        startMax++;
        output++;
    }

    return max;
}

2011年2月6日星期日

<转>Count the number of bits that are on in an unsigned integer(计算一个无符整数中1Bit的个数)

计算一个无符号整数中有多少的Bit为1
原创整理,转载请注明出处。
这是一个经常遇到的经典问题,这里分两个部分讲解和总结,首先对讲解现有的算法,然后再讲解一些改进算法。

1.循环法(Iterated Count)
int bitcount (unsigned int n)  
{
int count=0;      
    while (n)  {
        count += n & 0x1u ;
        n >>= 1 ;
      }
return count ;
}
最容易理解和想到的方法。对每一位依次判断是否为1,如果是就在count上加1。
循环的次数是常数(n的位数)。在1比较稀疏的时候效率低,可用方法2改进。
2.Bit1稀疏 Sparse Ones
int bitcount (unsigned int n)  
{
int count=0 ;
         while (n)  {
         count++ ;
         n &= (n - 1) ;
     }
     return count ;
}

理解这个算法的核心,只需理解2个操作:
1> 当一个数被减1时,他最右边的那个值为1的Bit将变为0,同时其右边的所有的Bit都会变成1。
2>“&=”,位与并赋值操作。去掉已经被计数过的1,并将改值重新设置给n.

这个算法循环的次数是bit位为一的个数。也就说有几个Bit为1,循环几次。对Bit为1比较稀疏的数来说,性能很好。如:0x1000 0000, 循环一次就可以。

3.密集1的算法 Dense Ones


int bitcount (unsigned int n)
{
     int count = 8 * sizeof(int) ;
     n ^= (unsigned int) -1 ;
     while (n)
    {
        count-- ;
        n &= (n - 1) ;
     }
     return count ;
}

4.8bit静态表查找法 Precompute_8bit
      static int bits_in_char [256] = {
    0, 1, 1, 2, 1, 2, 2, 3, 1, 2, 2, 3, 2, 3, 3, 4, 1, 2, 2, 3, 2, 3, 3, 4, 2,
    3, 3, 4, 3, 4, 4, 5, 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5, 2, 3,
    3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3,
    4, 3, 4, 4, 5, 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, 2, 3, 3, 4,
    3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5,
    6, 6, 7, 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5, 2, 3, 3, 4, 3, 4,
    4, 5, 3, 4, 4, 5, 4, 5, 5, 6, 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5,
    6, 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, 2, 3, 3, 4, 3, 4, 4, 5,
    3, 4, 4, 5, 4, 5, 5, 6, 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, 3,
    4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, 4, 5, 5, 6, 5, 6, 6, 7, 5, 6,
 6, 7, 6, 7, 7, 8
};
   int bitcount (unsigned int n)     
   {
      int count = 8 * sizeof(int) ;
      n ^= (unsigned int) -1 ;
      while (n)
      {
         count-- ;
         n &= (n - 1) ;
      }
      return count ;
   }
 
使用静态数组表,列出所有8bit(256个)无符号数含有Bit1的个数。将32Bit 的n分4部分,直接在表中找到对应的Bit1的个数,然后求和。
这是最快的方法了。缺点是需要比较大的内存。

<转>What is the minimum number instructions required to swap Odd and even bits in an uinteger

well ths soultion will be like
1) let the number be A = 10101111
2) A1 = A & 10101010 = 10101010
3) A2 = A & 01010101 = 00000101
4) A1 = A1 >> 1 = 01010101
5) A2 = A2 << 1 = 00001010
6) Answer = A1 | A2 = 01011111
so u require 5 instructions

reverse bits

翻转一个char的8个bits

char bitReverse(char a)
{
 char b = 0;
 for(int i = 0; i < 8; i++)
 {
  if(a & 1)
   b = b | (1 << (7 - i));
  a = a >> 1;
 }
 return b;
}

<转>Find the Maximum of 2 numbers without using any if-else or any other comparison operator

Suppose 2 numbers are A and B .
Perform the operation A-B and extract the MSB .let it be k. Now if k =1 then A>B else B>A (2's complement)..
return (1-k)*A+k*B. This will alyways return the maximum of A&B

int a,b=0;
a = 7;
b = 9;
int diff = (unsigned int)(a-b) >> 31;
printf("\nDiff : %d\n",diff);
int sum = (1-diff)*a + (diff*b);
printf("\n Max of %d and %d is : %d\n",a,b,sum);

2011年2月5日星期六

<转>atoi和itoa的实现

//atoi的实现
#include<iostream>
using namespace std;
int atio1(char *s)
{
int sign=1,num=0;
    if(*s=='-')
        sign=-1;
    s++;
    while((*s)!='\0')
    {
        num=num*10+(*s-'0');
        s++;
    }   
    return num*sign;   
}
//itoa的实现
char *itoa(int num, char *str, int radix)
{
    char* ptr = str;
    int i;
    int j;

    while (num)
    {
        *ptr++  = string[num % radix];
        num    /= radix;

        if (num < radix)
        {
            *ptr++  = string[num];
            *ptr    = '\0';
            break;
        }
    }

    j = ptr - str - 1;

    for (i = 0; i < (ptr - str) / 2; i++)
    {
        int temp = str[i];
        str[i]  = str[j];
        str[j--] = temp;
    }

    return str;
}

2011年2月4日星期五

<转>aligned malloc 实现

I checked it it works !!
#include <stdio.h>
#include <stdlib.h>

/*************************************************
Name :- aligned_malloc
Arguments:- number of bytes & Alignment Boundry
Return :- NULL on error
valid pointer on success
Working :- It will allocate memory with starting address
multiple of alignment passed and returns pointer
to it on success.
Ex.
aligned_malloc(50,128);
This will allocate 50 bytes of memory with
starting address multiple of 128.
*************************************************/
void *aligned_malloc(size_t bytes, size_t alignment)
{
        void *p1 ,*p2; // basic pointer needed for computation.

        if((p1 =(void *) malloc(bytes + alignment + sizeof(size_t)))==NULL)
                return NULL;

        size_t addr=(size_t)p1+alignment+sizeof(size_t);
        p2=(void *)(addr - (addr%alignment));

        *((size_t *)p2-1)=(size_t)p1;
        return p2;
}

/************************************************
Name :- aligned_free
Arguments :- pointer to be freed
Returns :- Nothing
*************************************************/
void aligned_free(void *p )
{
        free((void *)(*((size_t *) p-1)));
}

memalign函数可以直接实现这个功能,限制是alignment必须是2的power

2011年1月25日星期二

<转>不用临时变量交换两个数的值

当要交换两个数的值时,通常的做法是定义一个临时变量,然后再进行交换。那么能不能不用临时变量而交换两个数的值呢?可以的!C语言提供的异或运算就可以实现这样的操作。

异或运算符^也称XOR运算符,它的规则是若参加运算的两个二进位同号,则结果为0(假);异号为1(真)。即0 ^ 0 = 0, 0 ^ 1 = 1, 1 ^ 0 = 1, 1 ^ 1 = 0。

例:
#include

int main(int argc, char *argv[])
{
int a = 2, b = 6;

a = a ^ b;
b = b ^ a;
a = a ^ b;

printf("a = %d b = %d\n", a, b);

return 0;
}


结果如下:

a = 6 b = 2


分析:

前两个赋值语句:“a = a ^ b;”和“b = b ^ a;”相当于b = b ^ (a ^ b),而b ^ a ^ b等于a ^ b ^ b。b ^ b的结果为0,因为同一个数与相向相^,结果必为0。因此b的值等于a ^ 0,即a,其值为2。

再执行第三个赋值语句:“a = a ^ b”。由于a的值等于(a ^ b),b的值等于(b ^ a ^ b),因此,相当于a = a ^ b ^ b ^ a ^ b,即a的值等于a ^ a ^ b ^ b ^ b,等于b。

2007.06.02

今天又发现另外两种方法,特补上。

方法一
void swap(int *p, int *q)
{
*p = *p + *q;
*q = *p - *q;
*p = *p - *q;
}


方法二

void swap(int *p, int *q)
{
*p = *p + *q - (*q = *p);
}


原理为算术运算符的结合顺序为自左至右。