程序员面试题精选100题(06)-二元查找树的后序遍历结果[数据结构]
题目:输入一个整数数组,判断该数组是不是某二元查找树的后序遍历的结果。如果是返回true,否则返回false。
例如输入5、7、6、9、11、10、8,由于这一整数序列是如下树的后序遍历结果:
8
/ \
6 10
/ \ / \
5 7 9 11
因此返回true。
如果输入7、4、6、5,没有哪棵树的后序遍历的结果是这个序列,因此返回false。
分析:递归问题
#include <iostream> using namespace std; bool check(int arry[],int beg,int end) { if(beg > end || arry==NULL) { return false; } if(beg == end) return true; int change = end; while(true) { if(change>=beg && arry[change] >= arry[end]) { change--; } else break; } /*int change = end-1; for(;change>=0;--change) { if(arry[change]<arry[end]) break; }*/ int left = change; while(left>=beg && arry[left]<arry[end]) { left--; } if(left>=beg) return false; //recurs return check(arry,beg,change) && check(arry,change+1,end-1); } int main() { //int arry[] = {5,7,6,9,11,10,8}; int arry[] = {7,4,6,5}; bool ispostorder = check(arry,0,sizeof(arry)/sizeof(int)-1); if(ispostorder) cout << "yes postorder..." << endl; else cout << "not postorder..." << endl; return 0; }答案:
bool verifySquenceOfBST(int squence[], int length) { if(squence == NULL || length <= 0) return false; // root of a BST is at the end of post order traversal squence int root = squence[length - 1]; // the nodes in left sub-tree are less than the root int i = 0; for(; i < length - 1; ++ i) { if(squence[i] > root) break; } // the nodes in the right sub-tree are greater than the root int j = i; for(; j < length - 1; ++ j) { if(squence[j] < root) return false; } // verify whether the left sub-tree is a BST bool left = true; if(i > 0) left = verifySquenceOfBST(squence, i); // verify whether the right sub-tree is a BST bool right = true; if(i < length - 1) right = verifySquenceOfBST(squence + i, length - i - 1); return (left && right); }
从左到右,感觉这里for比while好些,oj上没有AC不知道没考虑那种情况???
=====================================================
程序员面试题精选100题(07)-翻转句子中单词的顺序[算法]
题目:输入一个英文句子,翻转句子中单词的顺序,但单词内字符的顺序不变。句子中单词以空格符隔开。为简单起见,标点符号和普通字母一样处理。
例如输入“I am astudent.”,则输出“student. a am I”。
由于本题需要翻转句子,我们先颠倒句子中的所有字符。这时,不但翻转了句子中单词的顺序,而且单词内字符也被翻转了。我们再颠倒每个单词内的字符。由于单词内的字符被翻转两次,因此顺序仍然和输入时的顺序保持一致。
也可以先翻转单词顺序,然后再全部翻转
扩展:左旋右旋问题
========================================================
程序员面试题精选100题(08)-求1+2+...+n[C/C++/C#]
题目:求1+2+…+n,要求不能使用乘除法、for、while、if、else、switch、case等关键字以及条件判断语句(A?B:C)。
这个的确够发散,定义一个类,我们new一含有n个这种类型元素的数组,那么该类的构造函数将确定会被调用n次
============================================================
程序员面试题精选100题(09)-链表中倒数第k个结点[数据结构]
题目:输入一个单向链表,输出该链表中倒数第k个结点。链表的倒数第0个结点为链表的尾指针。
分析:快慢指针。
扩展:输入一个单向链表。如果该链表的结点数为奇数,输出中间的结点;如果链表结点数为偶数,输出中间两个结点前面的一个
==================================================================
程序员面试题精选100题(10)-排序数组中和为给定值的两个数字[算法]
题目:输入一个已经按升序排序过的数组和一个数字,在数组中查找两个数,使得它们的和正好是输入的那个数字。要求时间复杂度是O(n)。如果有多对数字的和等于输入的数字,输出任意一对即可。
例如输入数组1、2、4、7、11、15和数字15。由于4+11=15,因此输出4和11。
分析:1.暴力C(2,n)复杂度O(n^2)
2.这个没用利用到有序这个条件,优化两个指针向中间靠拢。复杂度O(n)
扩展:
1.输入一个数组,判断这个数组中是不是存在三个数字i, j, k,满足i+j+k等于0
先排序O(nlogn),然后对于每个元素,采用上述算法判断是否有两个数和为该值,复杂度为O(n^2)
2. 如果输入的数组是没有排序的,但知道里面数字的范围,其他条件不变,如何在O(n)时间里找到这两个数字?
知道数字范围那就计数排序呗,其他同O(n)
3. 如果不知道数字范围呢?
这个就要依靠hash了,先O(n)hash,然后对于A查找是否hash存在K-A,存在即找到。复杂度O(n)
4. google面试题:无序数组是否存在连续几个数的和等于N
分析:1.暴力O(n^3)
2.优化下f(I,n)=f(I,n-1)+a[i][n]一趟O(n),对于n个i总复杂度为O(n^2)
3.快慢指针I,j。如果小于K,j增加;否则i增加,需要注意I==J的情况,ij不回溯,最多2n步,所以复杂度为O(n)