访问量:AmazingCounters.com

我的github链接:https://github.com/GuoChuanrui

刷题

    面试题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] != '\0')
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 }

 

posted @ 2016-06-04 12:03  郭传瑞  阅读(197)  评论(0编辑  收藏  举报