面试题(二)
来源:互联网 发布:常用路由选择算法 编辑:程序博客网 时间:2024/04/29 21:14
注:不喜勿喷
//21.合并两个排序的链表//输入两个递增排序的链表,合并这两个链表并使新链表中的节点仍然是递增的,例如,链表1和//链表2,则合并之后的升序链表如链表3所示,节点定义如下:struct ListNode{ int _value; ListNode* _next;};ListNode* merge(ListNode* phead1,ListNode* phead2){ if(phead1 == nullptr) return phead2; if(phead2 == nullptr) return phead1; ListNode* newroot = nullptr; if(phead1->_value < phead2->_value) { newroot = phead1; newroot->_next = merge(phead1->_next,phead2); } else { newroot = phead2; newroot->_next = merge(phead1,phead2->_next); } return newroot;}//22.树的子结构//输入两棵二叉树A和B,判断B是不是A的子结构。二叉树结点的定义如下:struct BinaryTreeNode{ double _value; BinaryTreeNode* _left; BinaryTreeNode* _right;};typedef BinaryTreeNode Node;bool BisAchildTree(Node* root1, Node* root2){ bool result = false; if(root1 != nullptr && root2 != nullptr) { if(Equal(root1->_value,root2->_value)) { result = IsAhasB(root1,root2); } if(!result) result = BisAchildTree(root1->_left,root2); if(!result) result = BisAchildTree(root1->_right,root2); } return result;}bool IsAhasB(Node* root1,Node* root2){ if(root1 == nullptr) return false; if(root2 == nullptr) return true; bool resultleft = false; bool resultright = false; if(!Equal(root1->_value,root2->_value)) { return false; } resultleft = IsAhasB(root1->_left,root2->_left); resultright = IsAhasB(root1->_right,root2->_right); return resultleft && resultright;}bool Equal(double x,double y){ if((x - y) > - 0.0000001 && (x -y) < 0.0000001) { return true; } return false;}//23.二叉树的镜像//请完成一个函数,输入一棵二叉树,该函数输出它的镜像,二叉树的节点定义如下:struct BinaryTreeNode2{ int _value; BinaryTreeNode2* _left; BinaryTreeNode2* _right;};typedef BinaryTreeNode2 Node;void BinaryMirror(Node* root){ if(nullptr == root) return; swap(root->_left,root->_right); BinaryMirror(root->_left); BinaryMirror(root->_right);}//24.对称的二叉树//实现一个函数,用来判断一棵二叉树是不是对称的,如果一棵二叉树和它的镜像一样,那么它是对称的;bool IsSymmetrical(Node* root){ return _IsSymmetrical(root,root);}//针对前序遍历:根左右//对称序列的谦虚遍历是:根右左bool _IsSymmetrical(Node* root1,Node* root2){ if(root1 == nullptr && root2 == nullptr) return true; if(root1 == nullptr || root2 == nullptr) return false; if(root1->_value != root2->_value) { return false; } return _IsSymmetrical(root1->_left,root2->_right) && _IsSymmetrical(root1->_right,root2->_left);}//25.顺时针打印矩阵//输入一个矩阵,按照从外向里以顺时针的顺序依次打印出每一个数字,如,输入如下矩阵:// 1 2 3 4// 5 6 7 8// 9 10 11 12//13 14 15 16//依次打印出来的顺序是:1,2,3,4,8,12,16,15,14,13,9,5,6,7,11,10void _PrintMatre(int* arr,int row,int col,int start);void PrintMatRe(int* arr,int row,int col){ if(nullptr == arr || row <= 0 || col <= 0) return; int start = 0; while(row > start*2 && col > start*2) { _PrintMatre(arr,row,col,start); ++start; }}void _PrintMatre(int* arr,int row,int col,int start){ int endRow = row - 1 - start; int endCol = col - 1 - start; //从左往右 if(start <= endCol) { for(int i = start; i <= endCol; i++) { cout<<arr[start*col+i]<<" "; } } //从上到下 if(start <= endRow) { for(int i = start+1; i <= endRow; i++) { cout<<arr[i*col+endCol]<<" "; } } //从右往左,防止出现一列,一行的现象 if(start < endCol && start < endRow) { for(int i = endCol-1; i >= start; --i) { cout<<arr[endRow*col+i]<<" "; } } //从下到上,防止出现一列,一行的现象 if(start < endCol && start < endRow) { for(int i = endRow-1; i > start; --i) { cout<<arr[i*col+start]<<" "; } }}//26.包含min函数的栈//定义一个栈的数据结构,请在该类型中实现一个能够得到栈的最小元素的min函数,在该栈中,调用//min,push及pop的时间复杂度为O(1)//分析:栈:先进后出,尾插尾删,数据结构不能改变//必须保证我们每次在执行push和pop操作的时候还能知道栈里面的最小元素,所以需要引进辅助栈template <class T>class Stack{private: T* _arr; int _size; int _capacity;public: Stack() :_arr(NULL),_size(0),_capacity(0) {} ~Stack() { if(_arr != NULL) { free(_arr); } _arr = NULL; _size = _capacity = 0; } void Push(const T& value) { checkcapacity(); _arr[_size] = value; ++_size; } void Pop() { if(_size == 0) return; --_size; } void checkcapacity() { if(_size >= _capacity) { _capacity = _capacity*2+1; T* arr = malloc(_capacity * sizeof(T)); for(int i = 0; i < _size; i++) { arr[i] = _arr[i]; } free(_arr); _arr = arr; } }};//27.栈的压入,弹出序列//输入两个整数序列,第一个序列表示栈的压入顺序,请判断第二个序列是否是该栈的弹出序列,假设//压入栈的所有数字均不相等,例如,序列{1,2,3,4,5}是某栈的压栈序列,序列{4,5,3,2,1}//是该栈序列对应得一个弹出序列,但是{4,3,5,1,2}就不可能是该压栈序列的弹出序列bool IsPopOrder(int* arr1,int *arr2,int length){ assert(arr1 && arr2); if(length <= 0) return false; int* p1 = arr1; int* p2 = arr2; stack<int> _st; int j = 0; int i = 0; for(; i < length; i++) { while(_st.empty() || _st.top() != p2[i]) { if(j == length) { break; } _st.push(p1[j]); ++j; } if(_st.top() != p2[i]) { break; } cout<<_st.top()<<" "; _st.pop(); } cout<<endl; if(_st.empty() && i == length) return true; return false;}//28.从上到下打印二叉树//不分行从上到下打印二叉树:从上到下打印出二叉树的每个节点,同一层的节点按照从左到右的顺序//打印,例如:输入,打印;,二叉树定义如下:struct BinaryTreeNode{ int _value; BinaryTreeNode* _left; BinaryTreeNode* _right;};//分析:创建一个队列,按照先进先出的队列层序遍历访问每一个节点typedef BinaryTreeNode Node;#include<queue>void LevelOrder(Node* root){ assert(root); queue<Node*> q; q.push(root); while(!q.empty()) { Node* cur = q.top(); cout<<cur->_value<<" "; if(cur->_left != NULL) { q.push(cur->_left); } if(cur->_right != NULL) { q.push(cur->_right); } q.pop(); }}#include <queue>//29.分行从上到下打印二叉树void LevelOrderAndLine(Node* root){ assert(root); queue<Node*> q; q.push(root); int curlevel = 1; int nextlevel = 0; while(!q.empty()) { Node* cur = q.front(); cout<<cur->_value<<" "; if(cur->_left != NULL) { q.push(cur->_left); ++nextlevel; } if(cur->_right != NULL) { q.push(cur->_right); ++nextlevel; } q.pop(); if(--curlevel == 0) { cout<<endl; curlevel = nextlevel; nextlevel = 0; } }}//30.打印之字形二叉树//上到右,右到左,左到右,右到左,以此类推;//分析,两个栈一个存放节点顺序是左右---偶数层,一个存放节点顺序是右左---奇数层#include <stack>void LevelOrderAndLineZHI(Node* root){ assert(root); stack<Node*> stack[2]; int current = 0;//奇数层 int next = 1;//偶数层 stack[current].push(root); while(!stack[0].empty() || !stack[1].empty()) { Node* cur = stack[current].top(); cout<<cur->_value<<" "; stack[current].pop(); if(current == 0) { if(cur->_left != NULL) { stack[next].push(cur->_left); } if(cur->_right != NULL) { stack[next].push(cur->_right); } } else//current == 1,当前层在偶数层 { if(cur->_right != NULL) { stack[next].push(cur->_right); } if(cur->_left != NULL) { stack[next].push(cur->_left); } } if(stack[current].empty()) { cout<<endl; current = 1 - current; next = 1 - next; } }}//31.二叉搜索树的后序遍历序列//输入一个整数数组,判断该数组是不是某二叉搜索树的后序遍历结果,如果是则返回true,否则返回//false,假设输入的数组的任意两个数字都互不相同,例如输入数组{5,7,6,9,11,10,8},则返回//true,因为这个证书序列是图中二叉搜索树的后序遍历结果,如果输入的数组是{7,4,6,5},则由于//没有那颗二叉搜索树的后序遍历结果是这个序列,因此返回false;//分析:后序遍历--->左右根,根节点是最后一个节点,而且二叉搜索树,左子树比根小//右子树比根大bool IsBackOrder(int* arr,int len){ if(arr == NULL && len <= 0) { return false; } int* root = arr + len - 1; int i = 0; for(; i < len-1; i++) { if(arr[i] > *root) { break; } } int j = i; for(; j < len-1; j++) { if(arr[j] < *root) { return false; } } bool IsLEFT = true; if(i > 0) { IsLEFT = IsBackOrder(arr,i); } bool IsRIGHT = true; if(j < len-1) { IsRIGHT = IsBackOrder(arr+i,len-i-1); } return IsLEFT && IsRIGHT;}//32.二叉树中和为某一路径的值void _PathFind(Node* root,const int key,int& value,stack<int>& q){ if(nullptr == root) return; q.push(root->_value); value += root->_value; if(value == key && root->_left == NULL && root->_right == NULL) { while(!q.empty()) { cout<<q.top()<<" "; q.pop(); } } if(root->_left != NULL) { _PathFind(root->_left,key,value,q); } if(root->_right != NULL) { _PathFind(root->_right,key,value,q); } value -= q.top(); q.pop();}void PathFind(Node* root,const int key){ assert(root); int value = 0; stack<int> q; _PathFind(root,key,value,q);}//用vector做可以将所有的访问完全//33.复杂链表的复制过程://请实现一个函数复制一个复杂链表,在复杂链表中,每个节点除了有一个next指针指向下一个节点//还有一个sib指针指向任意一个节点或者NULL,节点定义如下:struct ComplexListNode{ int _value; ComplexListNode* _next; ComplexListNode* _pSib; ComplexListNode(int value) :_value(value),_next(NULL),_pSib(NULL) {}};//分析:分三步走的方法:第一步复制所有的节点,第二步复制所有的随机下一个节点的位置路径,//第三步拆分链表//第一步:复制所有的当前结点到下一个指向typedef ComplexListNode Node;Node* CopyComplexList(Node* root){ assert(root); CopyComplexNode(root); CopyComplexPath(root); Node* newRoot = ComplexListCut(root); return newRoot;}void CopyComplexNode(Node* root){ Node* cur = root; Node* next = cur; while(cur) { next = cur->_next; Node* newcur = new Node(cur->_value); cur->_next = newcur; newcur->_next = next; cur = next; }}void CopyComplexPath(Node* root){ Node* cur = root; Node* pnext = cur; Node* next = cur; while(cur) { next = cur->_next; pnext = cur->_pSib; if(pnext != NULL) { next->_pSib = pnext->_next; } cur = next->_next; }}Node* ComplexListCut(Node* root){ Node* curS = root; Node* curD = root->_next; Node* newRoot = curD; Node* cur = curD->_next; if(NULL == cur) { root->_next = NULL; return newRoot; } int count = 0; while(cur) { if((++count) % 2 == 1)//奇数 { curS->_next = cur; curS = curS->_next; } else { curD->_next = cur; curD = curD->_next; } cur = cur->_next; } return newRoot;}//34.二叉搜索树与双向链表//输入一颗二叉搜索树,将该二叉搜索树转换成一个排序的双向链表,要求不能创建任何新的节点,//只能调整树种节点指针的指向,二叉树节点定义如下struct BinaryTreeNode{ int _value; BinaryTreeNode* _left; BinaryTreeNode* _right;};//对于搜索二叉树而言,要想要生成一个有序的节点就是中序遍历---左根右typedef BinaryTreeNode Node;Node* BinaryTreeNodeToList(Node* root){ assert(root); Node* prev = NULL; ConvertNode(root,prev); Node* cur = root; while(cur != nullptr && cur->_left == nullptr) { cur = cur->_left; } return cur;}void ConvertNode(Node* root, Node*& prev){ if(nullptr == root) return; if(root->_left != nullptr) ConvertNode(root->_left,prev); root->_left = prev; if(prev != nullptr) prev->_right = root; prev = root; if(root->_right != nullptr) ConvertNode(root->_right,prev);}//35.二叉树的序列化和反序列化//36.字符串的排列//输入一个字符串,打印出该字符串中字符的所有排列,例如,输入字符串“abc”,将由abc所能//排列出来的所有字符串都打印出来;void PrintString(char* str,char* cur,int& count);void printString(char* str){ assert(str); int count = 0; PrintString(str,str,count); cout<<endl<<count<<endl;}void PrintString(char* str,char* cur,int& count){ if(*cur == '\0') { cout<<str<<" "; ++count; } else { for(char* ch = cur; *ch != '\0'; ++ch) { swap(*ch , *cur); PrintString(str,cur+1,count); swap(*ch , *cur); } }}//37.二叉搜索树的第K大节点//给定一棵二叉搜索树,请找出其中第K大的节点;//分析:利用中序遍历将二叉搜索树生成一个递增的数组,这样就可以找到第K大节点Node* GetKNode(Node* root,int& k){ if(nullptr == root) { return nullptr; } Node* Knode = GetKNode(root->left,k); if(--k == 0) return root; if(Knode == nullptr) Knode = GetKNode(root->right,k); return Knode;}//38.输入一个整形数组,数组里有正数也有负数,数组中的一个或者连续多个整数组成一个子数组,//求所有子数组的和的最大值,要求时间复杂度是O(N);//分析:审清题意,此处的和是连续的数组中元素的和,所以我们从1开始加到最后一个数,保存当前//此时减少前的最大值,然后不停更新最大值即可#include <assert.h>int GetchildArrSum(int* arr,int length){ assert(arr && length > 0); int maxSum = arr[0]; int prevSum = arr[0]; for(int i = 1; i < length; i++) { if(arr[i] < 0) { prevSum += arr[i]; } else if(arr[i] > prevSum + arr[i])//此时arr[i] >= 0 { maxSum = arr[i]; prevSum = arr[i]; } else { maxSum = prevSum + arr[i]; prevSum = maxSum; } } return maxSum;}//39.1~n整数中1出现的次数//题目:输入一个整数N,求1~n这n个整数的十进制表示中1出现的次数,例如:输入12,1~12这些整数//中包含1的数字有1,10,11,12,1总共出现了5次;int GetOneCount(int x){ assert(x > 0); if(x < 10) { return 1; } int count = 1; for(int i = 10; i <= x; i++) { int number = i; while(number != 0) { if(number % 10 == 1) ++count; number /= 10; } } return count;}//40.数组中数字出现的次数//题目:数组中只出现一次的两个数字//一个整型数组里除两个数字之外,其他数字都出现了两次,请写程序找出这两个只出现一次的数字//要求时间复杂度是O(N),空间复杂度是O(1)//分析:利用异或算法-->相同的两个数之间异或的结果是0;//第一步:首先将数组中所有的数字都异或一遍,求出两个不同数的异或值;//第二步:保存上个结果的异或值,找出该值中二进制表示中第一个1出现的位置(从右往左);//第三步:将数组分成两部分,将两个不同数分别放入这辆部分然后异或得出int FindPosOne(int result);void FindTwoDiffNumber(int* arr,int length, int* num1, int* num2){ assert(arr && length > 0); int result = 0; for(int i = 0; i < length; i++) { result ^= arr[i]; } int pos = FindPosOne(result); result = 1 << pos; *num1 = *num2 = 0; for(int i = 0; i < length; i++) { if(arr[i] & result) { *num1 ^= arr[i]; } else { *num2 ^= arr[i]; } }}int FindPosOne(int result){ int pos = 0; while(((result & 1) != 1) && pos < 32) { result = result >> 1; ++pos; } return pos;}//41.在一个数组中除了一个数字出现一次以外其余数字都出现三次,请找出那个数字;//这次不能再使用异或运算了,因为是三次,所以异或结果还是元素自己//分析:因为其余每个元素都出现了三次,那么每个元素的二进制中三次出现之和都是3的倍数,//那么所有的数字加起来除了唯一出现一次的那个数字意外都是3的倍数,所以我们使用二进制每个位置//上面的值(0/1)的个数加起来然后%3,并且记录每个位置上面的数目,这样%完以后将每个位置上面//的结果拼在一起就是所求的数的二进制值int FindOnlyOneNumber(int* arr, int length){ assert(arr && length > 0); int num[32] = {0}; int result; for(int i = 0; i < length; i++) { result = 1; for(int j = 0; j < sizeof(num)/sizeof(num[0]); j++) { if((arr[i] & result) != 0) { num[j] += 1; } result = result << 1; } } result = 0; for(int i = (sizeof(num)/sizeof(num[0]))-1; i >= 0 ; --i) { result += num[i] % 3; if(i != 0) { result = result << 1; } } return result;}
阅读全文
0 0
- 面试题(二)
- 面试题(二)
- 面试题(二)
- 面试题(二)
- 面试题(二)
- 面试题(二)
- 面试题(二)
- 面试题(二)
- 面试题(二)
- 面试题(二)J2EE
- SQL面试题 (二)
- 常见面试题(二)
- 微软面试题(二)
- 微软面试题(二)
- JAVA面试题(二)
- java面试题(二)
- @经典面试题(二)@
- 面试题整理(二)
- LeetCode.92 Reverse Linked List
- 新手微擎(微赞)学习之路二 --- 框架整体认知
- Python安装模块的问题
- Android_自定义遥控器按钮
- 函数 devm_kzalloc()
- 面试题(二)
- 2017年 CEEC 中国国际清洁能源博览会会刊会刊(参展商名录)
- 【MySQL锁之】InnoDB存储引擎及其锁机制
- js去掉字符串的空格回车换行
- Python3写一个计算年份是否是平年或闰年
- LeakCanary: 让内存泄露无所遁形
- Vue2+VueRouter2+Webpack+Axios 构建项目实战2017重制版(十四)在项目中使用 jQuery
- VC++6.0 双击dsw/dsp打开多个窗口
- 浏览器缓存