zoukankan      html  css  js  c++  java
  • 2013.5.12搜狐实习生笔试题(编码题部分)


    1.利用堆排序对数组进行排序。

     堆结构是把数组看成完全二叉树,除最后一层,每一层都是满的。堆分最大堆和最小堆,其中最大堆是指每一个子树中,根要比其两个孩子的值大,最小堆反之;数组元素升序需要用最大堆,降序用最小堆;这里使用最大堆。

    实现堆排序需要三个主要函数:建立最大堆,维持最大堆性质,和堆排序函数。

    建立最大堆(BuildMaxHeap):自底向上地维持最大堆性质,heapsize/2为最底下一层的父结点,即需要从结点下标为heapsize/2 ~ 0的结点调用维持最大堆性质的函数(MaxHeapify)。

    维持最大堆性质(MaxHeapify):将堆中某个元素调整到合适的位置(下沉);使之满足最大堆性质。

    堆排序函数(HeapSort):将堆顶(该堆的最大值)和堆底交换,并将heapsize减1,再调用函数使目前的堆维持最大堆性质。

     code:

     1 void Swap(int *A, int i, int j)
     2 {
     3     int tmp = A[i];
     4     A[i] = A[j];
     5     A[j] = tmp;
     6 }
     7 //维持最大堆性质
     8 void MaxHeapify(int *A, int i, int heapsize)
     9 {
    10     //递归版本
    11     //int nLeft = 2 * i + 1;
    12     //int nRight = 2 * i + 2;
    13     //int nLargrIndex;
    14     //if (A[nLeft] < A[nRight])
    15     //{
    16     //    nLargrIndex = nRight;
    17     //}
    18     //else
    19     //{
    20     //    nLargrIndex = nLeft;
    21     //}
    22     //if (A[i] < A[nLargrIndex])
    23     //{
    24     //    //swap(A, i , nLargeIndex)
    25     //    Swap(A, i, nLargrIndex);
    26     //    MaxHeapify(A, nLargrIndex, heapsize);
    27     //}
    28     //非递归版本
    29     int child; int tmp;
    30     for (tmp = A[i]; heapsize > 2 * i + 1; i = child)
    31     {
    32         child = 2 * i + 1;
    33         //记录孩子中较大者下标
    34         if (child != heapsize - 1 && A[child + 1] > A[child])
    35         {
    36             child++;
    37         }
    38         //若当前的父亲比孩子小,则交换
    39         if (tmp < A[child])
    40         {
    41             A[i] = A[child];
    42         }
    43         else
    44             break;
    45     }
    46     A[i] = tmp;//把原父节点放到合适的位置上
    47 }
    48 
    49 void BuildMaxHeap(int *A, int heapsize)
    50 {
    51     //从堆底的父节点开始向上建立堆,就是让每一个子堆具有最大堆性质,自底向上的
    52     for(int i = heapsize / 2; i >= 0; i--)
    53     {
    54         MaxHeapify(A, i, heapsize);
    55     }
    56 }
    57 
    58 void HeapSort(int *A, int heapsize)
    59 {
    60     BuildMaxHeap(A, heapsize);
    61     for (int i = heapsize - 1; i > 0; i--)
    62     {
    63         //交换堆顶和堆最后一个元素,堆个数减1
    64         Swap(A, 0, i);
    65         heapsize--;
    66         //保持最大堆性质
    67         MaxHeapify(A, 0, heapsize);
    68     }
    69 
    70 }


    2.已知rand7()生成1~7的随机数,写出rand10()。

     思想:利用进制的方法生成进制位上的元素,选择输出指定的范围。ps:直接扩充的方法产生的每个数概率不相等,中间的数概率会高些。

    code:

     1 //产生范围1~10
     2 int rand10()
     3 {
     4     int result;
     5     while (1)
     6     {    //利用7进制产生result,其范围是0-48
     7         result = 7 * (rand7() - 1) + rand7() - 1;
     8         //若范围在1~10,则break并返回
     9         if (result > 0 && result < 11)
    10         {
    11             break;
    12         }
    13     }
    14     return result;
    15      
    16 }

    3.设计算法,实现一个对数组左移k个元素的函数,要求时间复杂度为O(n)。

    此题在Programming Pearls Column2有相应介绍。主要思想是利用等式(arbr)r = ba,r表示reverse,例如序列{1,2,3,4,5,6,7},现在数组左移3位得到的结果为{4,5,6,7,1,2,3};利用前面介绍的等式,把原序列中的前3位,和剩下一部分分别反转,于是得到{3,2,1,7,6,5,4},再整体反转一次得到{4,5,6,7,1,2,3}即为最终结果。反转的时间复杂度为O(n),故满足题意,而且不需要额外的内存空间。

    code: 

     1 //对数组A 指定范围反转元素
     2 template <class T>
     3 void Reverse(T *A, int nStart, int nEnd)
     4 {
     5     int i;
     6     for (i = nStart; i < nStart + (1 + nEnd - nStart) / 2; ++i)
     7     {
     8         T tmp = A[i];
     9         A[i] = A[nEnd + nStart - i];
    10         A[nEnd + nStart - i] = tmp;
    11     }
    12 }
    13 template <class T>
    14 void LeftMoveKthElements(T *A, int k, int n)
    15 {
    16     //@Param n: Number of elements in array A
    17     //@Param k: left move k elements
    18     Reverse(A, 0, k - 1);
    19     Reverse(A, k, n - 1);
    20     Reverse(A, 0, n - 1);
    21 }


    实例:

     


    4.用最快的算法打印1~n的素数。

     思路:用筛选法和位运算。利用一个unsigned int的位数可代表32个数,于是n个元素只需要1+ n/32个unsigned int就够了。

    筛选法:遍历2~sqrt(n),把2~sqrt(n)的倍数 对应的位设为0(异或操作^)。 输出时把2~n对应位数非0的数输出即可。

     1 void printPrime(unsigned int n)
     2 {
     3     int nSize = (int)sqrt((double)n);
     4     //申请空间n个元素所需要的空间(按bit算)
     5     unsigned int *nArray = (unsigned int*)malloc((1 + n / 32) * sizeof(unsigned int));
     6     if (nArray == NULL)
     7     {
     8         throw ("malloc failed!");
     9     }
    10     for (int i = 0; i < 1 + n / 32; ++i)
    11     {
    12         nArray[i] = 0xFFFFFFFF;//initialization
    13     }
    14     for (int i = 2; i < nSize; ++i)
    15     {
    16         for (int j = 2 * i; j <= n; j += i)
    17         {
    18             //判断某位是否为0,非零则设为0,注意下面的判断语句的值不一定是1,而是某位上的1对应的数
    19             if ( (nArray[j >> 5] & (1 << (j % 32))) != 0 )
    20             {
    21                 nArray[j >> 5] ^= 1 << (j % 32);
    22             }
    23         }
    24     }
    25     int j = 0;
    26     for (int i = 2; i <= n; ++i)
    27     {
    28         //判断某位是否为0,非零则是素数,输出
    29         if ( (nArray[i >> 5] & (1 << (i % 32)) ) != 0 )
    30         {
    31             printf("%d ",i);
    32             ++j;
    33             if (j % 10 == 0)
    34             {
    35                 printf("\n");
    36             }
    37         }
    38         
    39     }
    40     free(nArray);
    41     nArray = NULL;
    42 }

    下面是打印1~1000的素数

    不经历风雨,怎么见彩虹!
  • 相关阅读:
    夺命雷公狗---PDO NO:9 使用PDO准备语句并执行语句3
    夺命雷公狗---PDO NO:9 使用PDO准备语句并执行语句2
    [LeetCode] Lowest Common Ancestor of a Binary Search Tree
    二叉树
    LeetCode Palindrome LinkList
    LeetCode Same Tree
    LeetCode Merge Sorted List
    LeetCode Remove Duplicated from Sorted List
    LeetCode Climbing Stairs
    LeetCode Count And Say
  • 原文地址:https://www.cnblogs.com/ivorfeng/p/3074822.html
Copyright © 2011-2022 走看看