面试题21包括min函数的栈 

面试题22栈的压入、弹出序列 

面试题23从上往下打印二叉树 

面试题24二叉搜索树的后序遍历序列 

面试题25二叉树中和为某一值的路径 

面试题26复杂链表的复制 

面试题27二叉搜索树与双向链表 

面试题28字符串的排列 

面试题29数组中出现次数超过一半的数字

面试题30最小的K个数

/****************************************************/

面试题21 包括min函数的栈 :定义栈的数据结构,请在该类型中实现一个可以得到栈的最小元素的min函数。在该栈中。调用min、push及pop的时间复杂度都是O(1)

思       路:申请一个与原来栈stack大小同样的栈tmpStack。用来保存当前栈中最小元素。stack压入一个元素,tmpStack也压入一个元素,该元素与tmpStack.top比較,大则压入top 否则压入该元素。

出栈同一时候出栈。

实现例如以下:

  1. template <typename> T;
  2. class Stack
  3. {
  4. public:
  5. Stack();
  6. ~Stack();
  7. void pop();
  8. void push(T &value);
  9. T min();
  10. private:
  11. stack<T> m_stack;
  12. stack<T> m_min;
  13. };
  14. void pop()
  15. {
  16. if (m_min.size() <= 0 || m_stack.size() <= 0)
  17. {
  18. return;
  19. }
  20. m_stack.pop();
  21. m_min.pop();
  22. }
  23. void push(T &value)
  24. {
  25.  
  26. if ( m_min.size() == 0 || value < m_min.top())
  27. {
  28. m_min.push(value);
  29.  
  30. }
  31. else
  32. {
  33. m_min.push(m_min.top());
  34. }
  35.  
  36. m_stack.push(value);
  37.  
  38. }
  39. T min()
  40. {
  41. if (m_min.size() > 0)
  42. {
  43. return m_min.top();
  44. }
  45. }

面试题22 栈的压入、弹出序列 :输入两个序列。第一个是栈的压入顺序,请推断第二个1、2、3、4、5、6则4、5、3、2、1是出栈顺序。而4、3、5、1、2就不可能是该压栈序列。

思路:

实现例如以下:

  1. bool IsPopOrder(const int *pPush, const int *pPop, int length)
  2. {
  3. const int *pPushNext = pPush;
  4. const int *pPopNext = pPop;
  5. bool result = false;
  6.  
  7. if (pPush == NULL || pPop == NULL || length <= 0)
  8. {
  9. return false;
  10. }
  11.  
  12. stack<const int> iStack;
  13.  
  14. while(pPopNext - pPop < length)/* 弹出序列还没有到头*/
  15. {
  16. while(iStack.top() != *pPopNext)
  17. {
  18. if (pPushNext - pPush == length)
  19. {
  20. break;
  21. }
  22.  
  23. iStack.push(*pPushNext);
  24. pPushNext++;
  25. }
  26.  
  27. if (iStack.top() != *pPopNext)
  28. {
  29. break;
  30. }
  31.  
  32. iStack.pop();
  33. pPopNext++;
  34. }
  35.  
  36. if (iStack.empty() && pPopNext - pPop == length)
  37. {
  38. return true;
  39. }
  40.  
  41. return false;
  42. }

面试题23 从上往下打印二叉树 。二叉树的层序遍历

实现例如以下:

  1. struct BinaryTreeNode
  2. {
  3. int data;
  4. BinaryTreeNode *lchild;
  5. BinaryTreeNode *rchild;
  6. };
  7. void LevelOrder(BinaryTreeNode *root)
  8. {
  9. BinaryTreeNode *pNode;
  10. if (root == NULL)
  11. {
  12. return;
  13. }
  14. queue<BinaryTreeNode> iQueue;
  15. iQueue.push(root);
  16. while(!iQueue.empty())
  17. {
  18. pNode = iQueue.front();
  19. if (pNode->lchild != NULL)
  20. {
  21. iQueue.push(pNode->lchild);
  22. }
  23. if (pNode->rchild != NULL)
  24. {
  25. iQueue.push(pNode->rchild);
  26. }
  27.  
  28. printf("%d",pNode->data);
  29. iQueue.pop();
  30. }
  31. }

面试题24 二叉搜索树的后序遍历序列 ,给出一个数组,推断是否是二叉搜索树的后序遍历序列

思路:最后一个结点的值大于左子树的随意值。小于右子树的随意值

实现例如以下:

  1. int IsSerchTree(int *squeue, int length)
  2. {
  3. int i,j;
  4.  
  5. if (squeue == NULL || length <= NULL)
  6. {
  7. return false;
  8. }
  9.  
  10. for (i = 0; i < length; i++)
  11. {
  12. if (squeue[i] > squeue[length-1])
  13. {
  14. break;
  15. }
  16. }
  17.  
  18. for (j = i, j <length; j++)
  19. {
  20. if (squeue[j] < squeue[length -1])
  21. {
  22. return false;
  23. }
  24. }
  25.  
  26. if ((true == IsSerchTree(squeue, i)
  27. && (true == IsSerchTree(squeue + i,length - i - 1)))
  28.  
  29. {
  30. return true;
  31. }
  32.  
  33. }

面试题25 二叉树中和为某一值的路径

注意:vector 与 stack和queue的差别

vector能够从头部删除节点,也能够从尾部遍历整个结构

实现例如以下:

  1. struct BinaryTreeNode
  2. {
  3. int data;
  4. BinaryTreeNode *lchild;
  5. BinaryTreeNode *rchild;
  6. };
  7. void SumPathTree(BinaryTreeNode *root, int expectSum, vector<int> &iPath, int currentSum)
  8. {
  9. if (root == NULL)
  10. {
  11. return;
  12. }
  13.  
  14. /* 採用前序遍历的方式,先处理根节点 */
  15. currentSum += root->data;
  16. iPatch.push_back(root->data);
  17.  
  18. if ((currentSum == expectSum)
  19. && (root->lchild == NULL && root->rchild == NULL)
  20. {
  21. for (iterator iter = iPath.begin(); iter < iPath.end(); iter++)
  22. {
  23. printf("%d", *iter);
  24. }
  25. printf("\n");
  26. }
  27.  
  28. if (root->lchild != NULL)
  29. {
  30. SumPathTree(root->lchild,expectSum,iPath,currentSum);
  31. }
  32.  
  33. if (root->rchild != NULL)
  34. {
  35. SumPathTree(root->rchild,expectSum,iPath,currentSum);
  36. }
  37.  
  38. /* 假设以上路径都没有期望的值。则回溯到调用之前的结点 递归结束之后,一定回到根结点 */
  39. iPath.pop_back();
  40. currentSum-=root->data;
  41.  
  42. }

面试题26 复杂链表的复制

struct ComplexListNode

{

int data;

ComplexListNode *next;

ComplexListNode *sibling;/* 指向不论什么一个结点 */

};

第一步:每一个节点后面赋值一个同样的结点

第二步:遍历偶数结点。将新结点中sibling指针指向该指的结点

第三步:将链表按奇数偶数。拆分成两个链表。

面试题27 二叉搜索树与双向链表 ,输入一个二叉搜索树,将一个二叉搜索树变成一个排序的双向链表

思路:採用中序遍历二叉树的方式,每次递归记录下来上次遍历到的结点,作为指针传入下次递归

实现例如以下:

  1. struct BinaryTreeNode
  2. {
  3. int data;
  4. BinaryTreeNode *lchild;
  5. BinaryTreeNode *rchild;
  6. };
  7. void ConvertTree(BinaryTreeNode *root, BinaryTreeNode **lastNode)
  8. {
  9. if (root == NULL)
  10. {
  11. return;
  12. }
  13.  
  14. ConvertTree(root->lchild,lastNode);
  15.  
  16. root->lchild = lastNode;
  17. if (*lastNode != NULL)
  18. {
  19. (*lastNode)->rchild = root;
  20. }
  21. (*lastNode) = root;
  22.  
  23. ConvertTree(root->rchild,lastNode);
  24. }
  25.  
  26. BinaryTreeNode *GetHeadNode(BinaryTreeNode *root)
  27. {
  28. BinaryTreeNode *head;
  29. if (root == NULL)
  30. {
  31. return NULL;
  32. }
  33.  
  34. head = root;
  35. while (head->lchild)
  36. {
  37. head = head->lchild;
  38. }
  39. return head;
  40. }

面试题28 字符串的排列

比如:比如输入abc 输出abc的六种排列组合 abc  bac ……

实现例如以下:

  1. #include <iostream>
  2.  
  3. void printOrderStr(char *str, int length, int index)
  4. {
  5.  
  6. char temp;
  7.  
  8. if (str == NULL || length == 0)
  9. {
  10. return;
  11. }
  12.  
  13. if (index == length)
  14. {
  15. for (int i = 0; i<length; i++)
  16. printf("%c",str[i]);
  17. printf("\n");
  18. }
  19.  
  20. for (int i = index; i < length; i++)
  21. {
  22. temp = str[index];
  23. str[index] = str[i];
  24. str[i] = temp;
  25.  
  26. printOrderStr(str, length, index+1);
  27.  
  28. temp = str[index];
  29. str[index] = str[i];
  30. str[i] = temp;
  31.  
  32. }
  33. }
  34. int main()
  35. {
  36. char str[] = {'a', 'b', 'c'};
  37.  
  38. printOrderStr(str, 3, 0);
  39.  
  40. }

扩展题,输入一个字符串输出字符串的各种组合,比如:输入abc 输出a、b、c、ab……abc

实现例如以下:

  1. #include<iostream>
  2. #include<vector>
  3. #include<cstring>
  4. using namespace std;
  5. #include<assert.h>
  6.  
  7. void Combination_m(char *string ,int number , vector<char> &result)
  8. {
  9. assert(string != NULL);
  10. if(number == 0)
  11. {
  12. static int num = 1;
  13. printf("第%d个组合\t",num++);
  14.  
  15. vector<char>::iterator iter = result.begin();
  16. for( ; iter != result.end() ; ++iter)
  17. printf("%c",*iter);
  18. printf("\n");
  19. return ;
  20. }
  21. if(*string == '\0')
  22. return ;
  23.  
  24. result.push_back(*string);
  25. Combination_m(string + 1 , number - 1 , result);
  26. result.pop_back();
  27. Combination_m(string + 1 , number , result);
  28. }
  29.  
  30. void Combination(char *string)
  31. {
  32. assert(string != NULL);
  33.  
  34. int i , length = strlen(string);
  35. for(i = 1 ; i <= 3 ; ++i)
  36. {
  37. vector<char> result;
  38. Combination_m(string , i ,result);
  39. }
  40. }
  41.  
  42. int main(void)
  43. {
  44. char str[] = "abc";
  45. Combination(str);
  46. getchar();
  47. return 0;
  48. }

面试题29 数组中出现次数超过一半的数字 。给定一个数组,当中有一个数组其个数超过一半。求该数

思路:

最简单的就是排序,求中位数。

採用一个数记录反复个数,一个数记录结果,详细实现例如以下:

  1. int FindMoreThanHalf(int num[], int length)
  2. {
  3. int times = 0;
  4. int result;
  5. if (num == NULL || length <=0 )
  6. {
  7. return 0;/* 非法输入*/
  8. }
  9.  
  10. result = num[0];
  11. times++;
  12. for (int i = 1; i < length; i++)
  13. {
  14.  
  15. if (num[i] == result)
  16. {
  17. times++;
  18. }
  19.  
  20. if (times == 0)
  21. {
  22. result = num[i];
  23. }
  24.  
  25. if (num[i] != result && times > 0 )
  26. {
  27. times--;
  28. }
  29. }
  30.  
  31. return times;
  32. }

面试题30 最小的K个数

  1. #include <stdlib.h>
  2. #include <stdio.h>
  3. /* 求最小的K个数 */
  4.  
  5. int partition(int *psArray, int num, int startIndex, int endIndex)
  6. {
  7. int iTemp;
  8. int i = startIndex;
  9. int j = endIndex;
  10.  
  11. if (psArray == NULL || num <= 0 || startIndex > endIndex || startIndex < 0 || endIndex < 0)
  12. {
  13. return 0;
  14. }
  15.  
  16. iTemp = psArray[0];
  17.  
  18. while (i < j)
  19. {
  20. while ((i < j) && (psArray[i] <= psArray[j]))
  21. j--;
  22.  
  23. if (i < j)
  24. {
  25. iTemp = psArray[i];
  26. psArray[i] = psArray[j];
  27. psArray[j] = iTemp;
  28. }
  29.  
  30. while((i < j) && (psArray[i] <= psArray[j]))
  31. i++;
  32.  
  33. if (i < j)
  34. {
  35. iTemp = psArray[i];
  36. psArray[i] = psArray[j];
  37. psArray[j] = iTemp;
  38. }
  39. }
  40. return i;
  41. }
  42. void FindMinKNum(int *psArray, int num, int k)
  43. {
  44. int i;
  45. int j;
  46. if (k > num)
  47. {
  48. return;
  49. }
  50.  
  51. i = partition(psArray,num,0,num-1);
  52. while (i != k-1)
  53. {
  54. if (i < k-1)
  55. {
  56. i = partition(psArray,num,i+1,num-1);
  57. }
  58. else
  59. {
  60. i = partition(psArray,num,0,i-1);
  61. }
  62. }
  63. for (j = 0; j <= i; j++)
  64. {
  65. printf(" %d", psArray[j]);
  66. }
  67. printf("\n");
  68.  
  69. }
  70. int main()
  71. {
  72. int a[]={3,4,5,1,2};
  73. FindMinKNum(a, 5, 2);
  74.  
  75. }

能够用O(n*logk)的时间复杂度加上O(k)的空间复杂度来实现。

  1. void GetLeastNumbers(int *psArray, int length, int k)
  2. {
  3. if (psArray == NULL || length < 0 || k < 0 || length < k)
  4. {
  5. return;
  6. }
  7.  
  8. multiset<int, greater<int> > iMultiset;
  9. multiset<int, greater<int> >::iterator iSetIterator;
  10.  
  11. for (int i = 0; i < length; i++)
  12. {
  13. if (i < k)
  14. {
  15. iMultiset.insert(psArray[i]);
  16. }
  17. else
  18. {
  19. if (psArray[i] < *(iMultiset.begin()))
  20. {
  21. iMultiset.erase(iMultiset.begin());
  22. iMultiset.insert(psArray[i]);
  23. }
  24. }
  25. }
  26. for (iSetIterator = iMultiset.begin(); iSetIterator != iMultiset.end(); iSetIterator++ )
  27. {
  28. printf(" %d", *iSetIterator);
  29. }
  30. printf("\n");
  31. }

【剑指Offer】俯视50题之21 - 30题的更多相关文章

  1. 【好书推荐】《剑指Offer》之硬技能(编程题12~16)

    本文例子完整源码地址:https://github.com/yu-linfeng/BlogRepositories/tree/master/repositories/sword <[好书推荐]& ...

  2. 【好书推荐】《剑指Offer》之硬技能(编程题7~11)

    本文例子完整源码地址:https://github.com/yu-linfeng/BlogRepositories/tree/master/repositories/sword <[好书推荐]& ...

  3. 【好书推荐】《剑指Offer》之硬技能(编程题1~6)

    本文例子完整源码地址:https://github.com/yu-linfeng/BlogRepositories/tree/master/repositories/sword 前一篇<[好书推 ...

  4. 剑指offer(第2版)刷题 Python版汇总

    剑指offer面试题内容 第2章 面试需要的基础知识 面试题1:赋值运算符函数 面试题2:实现Singleton模式  解答 面试题3:数组中重复的数字 解答 面试题4:二维数组中的查找 解答 面试题 ...

  5. 《剑指Offer》第二章(一)题3-8

    为春招实习做准备,记录一下<剑指Offer>里面的面试题 第二章 面试题3:数组之中的重复数字. 这个题吧,虽然不难,但是不知道为什么就是看了很久,可能很久没有做算法题了.最后面一句话说的 ...

  6. 【剑指Offer】50、数组中重复的数字

      题目描述:   在一个长度为n的数组里的所有数字都在0到n-1的范围内. 数组中某些数字是重复的,但不知道有几个数字是重复的.也不知道每个数字重复几次.请找出数组中任意一个重复的数字. 例如,如果 ...

  7. 剑指 Offer 61. 扑克牌中的顺子 + 简单题 + 思维

    剑指 Offer 61. 扑克牌中的顺子 Offer_61 题目描述 java代码 package com.walegarrett.offer; /** * @Author WaleGarrett * ...

  8. 剑指 Offer 58 - II. 左旋转字符串 + 简单题

    剑指 Offer 58 - II. 左旋转字符串 Offer_58_2 题目描述 java代码 package com.walegarrett.offer; /** * @Author WaleGar ...

  9. 剑指offer(50)数组中重复的数字

    题目描述 在一个长度为n的数组里的所有数字都在0到n-1的范围内. 数组中某些数字是重复的,但不知道有几个数字是重复的.也不知道每个数字重复几次.请找出数组中任意一个重复的数字. 例如,如果输入长度为 ...

随机推荐

  1. JavaSE-29 Java8的Lambda表达式

    概念说明 Lambda表达式是Java8提供的新特性,支持将代码块作为方法的参数. Lambda表达式支持使用简洁的代码创建只有一个方法的接口(函数式接口). 只包含一个方法的接口也称为函数式接口. ...

  2. gprc-java与golang分别实现服务端,客户端,跨语言通信(二.golang实现)

    1.编译器protoc, 下载地址:https://github.com/protocolbuffers/protobuf/releases  (下载对应的版本, 解压后放到go的bin中) 2.安装 ...

  3. 502 bad gateway nginx

    此方法可能仅对于我的问题有效 我在VMware虚拟机启动docker container nginx的,一开始启动nginx的contatiner,在浏览器是可以正常访问的,但次日重新访问时就报502 ...

  4. InnoDB INFORMATION_SCHEMA Metrics Table

    InnoDB INFORMATION_SCHEMA Metrics Table INNODB_METRICS表将所有InnoDB性能和资源相关计数器合并到一个INFORMATION_SCHEMA表中. ...

  5. cobbler 无人值守-介绍

    cobbler 介绍 快速网络安装linux操作系统的服务,支持众多的Linux版本,也支持网络安装windows系统 PXE的二次封装,将多种安装参数封装到一个菜单 它是由Python编写的 还可以 ...

  6. sorted倒序

    ''' sorted 可以排列list, reverse=True 可以倒序排列 ''' # # def list_Dict(x): # m = {} # for k,v in enumerate(x ...

  7. Root of AVL Tree

    04-树5 Root of AVL Tree(25 分) An AVL tree is a self-balancing binary search tree. In an AVL tree, the ...

  8. 3.3.3 使用 join 连接字段

        join 命令可以将多个文件结合在一起,每个文件里的每条记录,都共享一个键值(key),键值指的是记录中的主字段,通常会是用户名称.个人姓氏.员工编号之类的数据.举例来说,两个文件,一个列出所 ...

  9. IntrospectorCleanupListener监听器防止内存溢出

    <listener> <listener-class>org.springframework.web.util.IntrospectorCleanupListener</ ...

  10. MyBatis使用Mapper动态代理开发Dao层

    开发规范 Mapper接口开发方法只需要程序员编写Mapper接口(相当于Dao接口),由Mybatis框架根据接口定义创建接口的动态代理对象,代理对象的方法体同原始Dao接口实现类方法. Mappe ...