zoukankan      html  css  js  c++  java
  • 刷题

        面试题1:赋值运算符函数

      题目:如下为类型CMyString的声明,请为该类型添加赋值运算符函数。
      class CMyString
      {
      public:
        CMyString(char* pData = NULL);
        CMyString(const CMyString& str);
        ~CMyString(void);

      private:
      char* m_pData;
      };

      解析:先利用传进来的参数str创建一个临时实例temp,接着把temp.m_pData和实例自身的m_pData做交换。由于temp是一个局部变量,当程序运行到if外面时也就出了该变量的作用域,就会自动调用temp的析构函数,把temp.m_pData所指向的内存释放掉。又因为temp.m_pData已经指向实例之前m_pData的内存,这就相当于释放了实例之前的内存,那么现在实例的m_pData也指向了str的m_pData,完成了运算符重载。

      

     1 CMyString& CMyString::operator=(const CMyString& str)
     2 {
     3    if (this != &str)
     4    {
     5      CMyString temp(str);
     6 
     7      char* data = temp.m_pData;
     8      temp.m_pData = this->m_pData;
     9      this->m_pData = data;
    10    }
    11 
    12     return *this;
    13 }
    14   


      面试题2:二维数组中的查找

      题目:在一个二维数组中,每一行都按照从左到右递增的顺序排序,每一列都按照从上到下递增的顺序排序。请完成一个函数,输入这样的一个二维数组和一个整数,判断数组中是否含有该整数。 

      解析:首先选取一个角上的数字进行比较,这里我选择了右上角,可通过比较大小缩小查找的区域范围,找到则返回true,没找到返回false。例如:          

         

      

     1 bool Find(int* array, int rows, int columns, int number)
     2 {
     3     assert(array);
     4 
     5     if (array!=NULL && rows > 0 && columns > 0)
     6     {
     7         int row = 0;
     8         int col = columns - 1;
     9         while (row < rows && col >= 0)
    10         {
    11             if (array[row*columns + col] == number)
    12             {
    13                 return true;
    14             }
    15             else if (array[row*columns + col] > number)
    16             {
    17                 --col;
    18             }
    19             else
    20             {
    21                 ++row;
    22             }
    23         }
    24     }
    25 
    26     return false;
    27 }

      面试题3:替换空格

      题目:请实现一个函数,把字符串中的每个空格替换成“%20”。例如输入“We are happy.”,则输出“We%20are%20happy.”。

       解析:首先遍历一次字符串,统计空格数目,计算出替换之后的字符串长度。接着准备两个指针P1、P2,P1指向原字符串末尾,P2指向新字符串末尾,从后往前移动,遇到字符则复制,遇到空格则替换。

     1 //length为字符数组str的总容量
     2 void ReplaceBlank(char str[], int length)
     3 {
     4     if (str == NULL && length <= 0)
     5     {
     6         return;
     7     }
     8 
     9     //originalLen为字符串str的实际长度,numberOfBlank是空格数目
    10     int originalLen = 0;
    11     int numberOfBlank = 0;
    12     int i = 0;
    13     while (str[i] != '')
    14     {
    15         ++originalLen;
    16         if (str[i] == ' ')
    17         {
    18             ++numberOfBlank;
    19         }
    20 
    21         ++i;
    22     }
    23 
    24     //newLen是新字符串的长度
    25     int newLen = originalLen + numberOfBlank * 2;
    26     if (newLen > length)
    27     {
    28         return;
    29     }
    30     int originalIndex = originalLen;
    31     int newIndex = newLen;
    32     while (originalIndex >= 0 && newIndex > originalIndex)
    33     {
    34         if (str[originalIndex] == ' ')
    35         {
    36             str[newIndex--] = '0';
    37             str[newIndex--] = '2';
    38             str[newIndex--] = '%';
    39         }
    40         else
    41         {
    42             str[newIndex--] = str[originalIndex];
    43         }
    44         --originalIndex;
    45     }
    46 }

      

      面试题4:从尾到头打印链表

      题目:输入一个链表的头结点,从尾到头反过来打印出每个节点的值。

      链表节点定义如下:

      struct ListNode

      {

        int m_nKey;

        ListNode* m_pNext;

      };

       解析:可以用递归的思想。每访问到一个节点的时候,先递归输出它后面的节点,在输出该节点自身,这样链表的输出结果就反过来了。

    1 void PrintTailToHead(ListNode * pHead)
    2 {
    3     if (pHead)
    4     {
    5         PrintTailToHead(pHead->m_pNext);
    6         printf("%d  <- ", pHead->m_nKey);
    7     }
    8 }

      面试题5:重建二叉树

      题目:输入某二叉树的前序遍历和中序遍历的结果,请重建出该二叉树。假设输入的前序遍历和中序遍历的结果中都不含重复的数字。例如输入前序遍历序列{1,2,4,7,3,5,6,8}和中序遍历序列{4,7,2,1,5,3,8,6},则重建出如图的二叉树并输出它的头节点。二叉树节点的定义如下:

      struct BinaryTreeNode

      {

            int _data;

            BinaryTreeNode* _left;

            BinaryTreeNode* _right;                                                  

      };                

        

      解析:根据前序遍历和中序遍历的特点,可以发现,前序遍历的每一个节点,都是当前子树的根节点,同时以对应的节点为边界,就会把中序遍历的结果分为左子树和右子树。

        前序:1,2,4,7,3,5,6,8

        中序:4,7,2,1,5,3,8,6

        “1”是前序遍历节点中的第一个元素,它把中序遍历的结果分成“4,7,2”和“5,3,8,6”两个部分,即“1”的左右子树的遍历结果。找到前序遍历中对应的左右子树,就可以把“1”作为当前的根节点,然后依次递归下去,把左右子树的遍历结果也依次恢复出来。

     1 void ReBuild(char* PreOrder, char* InOrder, int TreeLen, BinaryTreeNode*& root)
     2 {
     3     //检查边界条件
     4     if (PreOrder == NULL || InOrder == NULL)
     5         return;
     6 
     7     //获得前序遍历的第一个节点
     8     BinaryTreeNode* temp = new BinaryTreeNode;
     9     temp->_data = *PreOrder;
    10     temp->_left = NULL;
    11     temp->_right = NULL;
    12 
    13     //如果节点为空,把当前节点复制到根节点
    14     if (root == NULL)
    15         root = temp;
    16 
    17     //如果当前树长度为1,那么已经是最后一个节点
    18     if (TreeLen == 1)
    19             return;
    20 
    21 
    22     //寻找子树长度
    23     char* pOrgInOrder = InOrder;
    24     char* pLeftEnd = InOrder;
    25     int templen = 0;
    26 
    27     //找到左子树的结尾
    28     while (*PreOrder != *pLeftEnd)
    29     {
    30         if (PreOrder == NULL || pLeftEnd == NULL)
    31         {
    32             return;
    33         }
    34         templen++;
    35 
    36         //记录临时长度,以免溢出
    37         if (templen > TreeLen)
    38         {
    39             break;
    40         }
    41         pLeftEnd++;
    42     }
    43 
    44     //寻找左子树长度
    45     int LeftLen = 0;
    46     LeftLen = (int)(pLeftEnd - pOrgInOrder);
    47 
    48     //寻找右子树长度
    49     int RightLen = 0;
    50     RightLen = TreeLen - LeftLen - 1;
    51 
    52     //重建左子树
    53     if (LeftLen > 0)
    54     {
    55         ReBuild(PreOrder + 1, InOrder, LeftLen, ((root)->_left));
    56     }
    57 
    58     //重建右子树
    59     if (RightLen > 0)
    60     {
    61         ReBuild(PreOrder + LeftLen + 1, InOrder + LeftLen + 1, 
    62 RightLen, ((root)->_right));
    63     }
    64 }

      

      面试题6:用两个栈实现队列
      题目:用两个栈实现一个队列。队列的声明如下,请实现它的两个函数appendTail和deleteHead,分别完成在队列尾部插入节点和在队列头部删除节点的功能。 

       template<typename T>

      class CQueue
      {
      public:
        CQueue(void);
        ~CQueue(void);

        void appendTail(const T& node);
        T deleteHead();

      private:
        stack<T> stack1;
        stack<T> stack2;
      };

       解析:用两个“后进先出”的栈实现一个“先进先出”的队列。有这样一种方法,令s1用来入栈,s2用来出栈。入队列时,压入s1中,出队列时,先把s1中的元素全部出栈压入s2中,在弹出s2的栈顶元素就可以了。   

        

     1 template<typename T>
     2 void CQueue<T>::appendTail(const T& x)
     3 {
     4     stack1.push(x);
     5 }
     6 
     7 template<typename T>
     8 T CQueue<T>::deleteHead()
     9 {
    10     if (stack2.size() <= 0)
    11     {
    12         while (stack1.size() > 0)
    13         {
    14             T& data = stack1.top();
    15             stack1.pop();
    16             stack2.push(data);
    17         }
    18     }
    19 
    20     if (stack2.size() == 0)
    21     {
    22         cout << "The queue is empty." << endl;
    23     }
    24 
    25     T head = stack2.top();
    26     stack2.pop();
    27 
    28     return head;
    29 }

      面试题7:旋转数组的最小数字

      题目:把一个数组最开始的若干个元素搬到数组的末尾,我们称之为数组的旋转。输入一个递增排序的数组的一个旋转,输出旋转数组的最小元素。例如数组{3,4,5,1,2}为{1,2,3,4,5}的一个旋转,该数组的最小值为1。

      解析:旋转之后的数组可以划分为两个排序的子数组,而且前面的子数组的元素都大于或者等于后面子数组的元素。最小的元素刚好是这两个子数组的分界线。在排序的数组中可以用二分查找。用两个指针分别指向数组的第一个元素和最后一个元素,当中间元素位于前面的递增数组,那么它应该大于或者等于第一个指针指向的元素,此时最小元素应该在中间元素的后面,可以把第一个指针指向该中间元素,缩小范围;同样,如果中间元素位于后面的递增子数组,它应该小于或者等于第二个指针指向的元素,最小元素位于中间元素的前面,可以把第二个指针指向该中间元素,缩小范围。重复查找知道找到最小。

      

     1 int FindMin(int* array, int length)
     2 {
     3     if (array == NULL || length <= 0)
     4     {
     5         cout << "Invalid" << endl;
     6 
     7     }
     8 
     9     int left = 0;
    10     int right = length - 1;
    11     int mid = left;
    12     while (array[left] >= array[right])
    13     {
    14         if (right - left == 1)
    15         {
    16             mid = right;
    17             break;
    18         }
    19 
    20         mid = left + (right - left) / 2;
    21         if (array[mid] >= array[left])
    22         {
    23             left = mid;
    24         }
    25         else if (array[mid] <= array[right])
    26         {
    27             right = mid;
    28         }
    29     }
    30     return array[mid];
    31 }
  • 相关阅读:
    CodeForces
    bzoj 2257: [Jsoi2009]瓶子和燃料
    【NOIP2009】Hankson 的趣味题
    51Nod 1203 JZPLCM
    bzoj 3751: [NOIP2014]解方程
    UOJ #11. 【UTR #1】ydc的大树
    Tenka1 Programmer Contest D
    bzoj 5000: OI树
    bzoj 1407: [Noi2002]Savage
    bzoj 3551: [ONTAK2010]Peaks加强版
  • 原文地址:https://www.cnblogs.com/guochuanrui/p/5557077.html
Copyright © 2011-2022 走看看