面试总结1

来源:互联网 发布:软件行业信息化建设 编辑:程序博客网 时间:2024/05/17 18:41
转载自:http://blog.csdn.net/v_july_v/article/details/68702511.把二元查找树转变成排序的双向链表
题目:
输入一棵二元查找树,将该二元查找树转换成一个排序的双向链表。
要求不能创建任何新的结点,只调整指针的指向。
10
/ \
6 14
/ \ / \
4 8 12 16
转换成双向链表
4=6=8=10=12=14=16。

首先我们定义的二元查找树节点的数据结构如下:

struct BSTreeNode{int m_nValue; // value of nodeBSTreeNode *m_pLeft; // left child of nodeBSTreeNode *m_pRight; // right child of node};
ANSWER:
This is a traditional problem that can be solved using recursion. 
For each node, connect the double linked lists created from left and right child node to form a full list.
/** * @param root The root node of the tree * @return The head node of the converted list. */BSTreeNode * treeToLinkedList(BSTreeNode * root) {  BSTreeNode * head, * tail;  helper(head, tail, root);  return head;}void helper(BSTreeNode *& head, BSTreeNode *& tail, BSTreeNode *root) {  BSTreeNode *lt, *rh;  if (root == NULL) {    head = NULL, tail = NULL;    return;  }  helper(head, lt, root->m_pLeft);  helper(rh, tail, root->m_pRight);  if (lt!=NULL) {    lt->m_pRight = root;    root->m_pLeft = lt;  } else  {    head = root;  }  if (rh!=NULL) {    root->m_pRight=rh;    rh->m_pLeft = root;  } else {    tail = root;  }}


3.求子数组的最大和

题目:
输入一个整形数组,数组里有正数也有负数。
数组中连续的一个或多个整数组成一个子数组,每个子数组都有一个和。
求所有子数组的和的最大值。要求时间复杂度为O(n)。
例如输入的数组为1, -2, 3, 10, -4, 7, 2, -5,和最大的子数组为3, 10, -4, 7, 2,
因此输出为该子数组的和18。
ANSWER: 
A traditional greedy approach.
Keep current sum, slide from left to right, when sum < 0, reset sum to 0.

int maxSubarray(int a[], int size) {  if (size<=0) error(“error array size”);  int sum = 0;  int max = - (1 << 31);  int cur = 0;  while (cur < size) {    sum += a[cur++];    if (sum > max) {      max = sum;    } else if (sum < 0) {      sum = 0;    }  }  return max;}

5.查找最小的k 个元素
题目:输入n 个整数,输出其中最小的k 个。
例如输入1,2,3,4,5,6,7 和8 这8 个数字,则最小的4 个数字为1,2,3 和4。
ANSWER:
This is a very traditional question...
O(nlogn): cat I_FILE | sort -n | head -n K
O(kn): do insertion sort until k elements are retrieved.
O(n+klogn): Take O(n) time to bottom-up build a min-heap. Then sift-down k-1 times.
So traditional that I don’t want to write the codes...
Only gives the siftup and siftdown function.
/** *@param i the index of the element in heap a[0...n-1] to be sifted upvoid siftup(int a[], int i, int n) {  while (i>0) {    int j=(i&1==0 ? i-1 : i+1);    int p=(i-1)>>1;    if (j<n && a[j]<a[i]) i = j;    if (a[i] < a[p]) swap(a, i, p);    i = p;  }  }void siftdown(int a[], int i, int n) {    while (2*i+1<n){    int l=2*i+1;    if (l+1<n && a[l+1] < a[l]) l++;    if (a[l] < a[i]) swap(a, i, l);    i=l;  }}

颠倒一个字符串。优化速度。优化空间。
void reverse(char *str) {  reverseFixlen(str, strlen(str));}void reverseFixlen(char *str, int n) {  char* p = str+n-1;  while (str < p) {    char c = *str;    *str = *p; *p=c;  }    }

★假设你有一个用1001 个整数组成的数组,这些整数是任意排列的,但是你知道所有的整数都在1 到1000(包括1000)之间。此外,除一个数字出现两次外,其他所有数字只出现一次。假设你只能对这个数组做一次处理,用一种算法找出重复的那个数字。如果你在运算中使用了辅助的存储方式,那么你能找到不用这种方式的算法吗?
ANSWER:
Sum up all the numbers, then subtract the sum from 1001*1002/2.
Another way, use A XOR A XOR B = B: 
int findX(int a[]) {
  int k = a[0]; 
  for (int i=1; i<=1000;i++)
    k ~= a[i]~i;
  }
  return k;
}

★不用乘法或加法增加8 倍。现在用同样的方法增加7 倍。
ANSWER:
n<<3;
(n<<3)-n;

第9题-----------------------------------
判断整数序列是不是二元查找树的后序遍历结果
题目:输入一个整数数组,判断该数组是不是某二元查找树的后序遍历的结果。
如果是返回true,否则返回false。
例如输入5、7、6、9、11、10、8,由于这一整数序列是如下树的后序遍历结果:
    8
   / /
  6  10
/ / / /
5 7 9 11
因此返回true。
如果输入7、4、6、5,没有哪棵树的后序遍历的结果是这个序列,因此返回false。

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);}

第10 题
翻转句子中单词的顺序。
题目:输入一个英文句子,翻转句子中单词的顺序,但单词内字符的顺序不变。
句子中单词以空格符隔开。为简单起见,标点符号和普通字母一样处理。
例如输入“I am a student.”,则输出“student. a am I”。
#include<iostream>#include<string>using namespace std;class ReverseWords{public:    ReverseWords(string* wo):words(wo){}    void reverse_()    {        int length=words->size();        int begin=-1,end=-1;        for(int i=0;i<length;++i){            if(begin==-1&&words->at(i)==' ')                continue;            if(begin==-1)            {                begin=i;                continue;            }            if(words->at(i)==' ')                end=i-1;            else if(i==length-1)                end=i;            else         continue;            reverse__(begin,end);    //1.字母翻转            begin=-1,end=-1;                   }        reverse__(0,length-1);       //2.单词翻转    }private:    void reverse__(int begin,int end)   //    {        while(begin<end)                   {            char t=words->at(begin);            words->at(begin)=words->at(end);            words->at(end)=t;            ++begin;            --end;        }    }    string* words;};int main(){    string s="I  am a student.";    ReverseWords r(&s);    r.reverse_();    cout<<s<<endl;       return 0;}




原创粉丝点击