笔试算法题(05):转换BST为双向链表 & 查找栈中的最小元素
出题:把二元查找树转变成排序的双向链表。输入一棵二元查找树,要求将该二元查找树按照中序转换成一个排序的双向链表,要求不能创建任何新的节点,只能调整指针的指向;
分析:
- 递归的思路,当前节点需要进行的处理,并使用递归调用和返回值将子问题链接起来;
- 首先明白二元查找树的特性,变成有序双向链表后当前根节点的左节点为其原来左子树的最右节点,右节点为其原来右子树的最左节点;因此策略就是针对当前根节点索引的子树,首先判断其为上层节点的右子树还是左子树,从而决定返回最右还是最右节点;然后再递归处理当前根节点的左右子树;
解题:
1 #include <stdio.h> 2 #include <malloc.h> 3 #include <string.h> 4 5 typedef struct Node { 6 int value; 7 Node *left; 8 Node *right; 9 } *NodePtr; 10 11 Node* MostLeft(Node *current) { 12 Node* temp=current; 13 while(temp->left!=NULL) { 14 temp=temp->left; 15 } 16 return temp; 17 } 18 19 Node* MostRight(Node *current) { 20 Node* temp=current; 21 while(temp->right!=NULL) { 22 temp=temp->right; 23 } 24 return temp; 25 } 26 27 Node* Transfer(Node *current, bool isRight) { 28 29 if(current==NULL) return NULL; 30 /** 31 * 在树结构被破坏之前预先查找好需要返回的节点 32 * */ 33 Node* turnback = (isRight ? MostLeft(current) : MostRight(current)); 34 /** 35 * 递归处理左右子树,将具体返回的节点推迟到子树解决 36 * */ 37 if(current->left!=NULL) { 38 current->left=Transfer(current->left,false); 39 current->left->right=current; 40 } 41 if(current->right!=NULL) { 42 current->right=Transfer(current->right,true); 43 current->right->left=current; 44 } 45 /** 46 * 根据isRight的值,和current是否有左右子树返回不同的节点 47 * */ 48 return turnback; 49 }
出题:定义stack数据结构,除Push和Pop函数外要求增加Min函数,其功能是找到stack中最小的元素,要求所有函数时间复杂度都是O(1);
分析:
- 使用辅助stack结构依次将目前的最小元素压入栈,设置CurMin元素记录当前stack中的最小元素,每次Push的新元素都与CurMin比较,若新元素更小则将其压入辅助栈;每次Pop元素都与CurMin比较,若就是CurMin元素则将辅助栈栈顶元素出栈;
解题:
1 class MyStack { 2 private: 3 int *array; 4 int capability; 5 int length; 6 int head; 7 int tail; 8 public: 9 MyStack(int n=10): array((int*)malloc(sizeof(int)*n)), head(0),tail(0),capability(n), length(0) {} 10 ~MyStack() {delete [] array;} 11 12 bool isFull() { 13 if(length == capability) return true; 14 return false; 15 } 16 bool isEmpty() { 17 if(length == 0) return true; 18 return false; 19 } 20 /** 21 * head当前的指向位置是下一次将push的元素的 22 * */ 23 bool push(int n) { 24 if(isFull()) return false; 25 array[head]=n; 26 head=(head+1)%(capability+1); 27 length++; 28 return true; 29 } 30 /** 31 * tail当前指向的位置是下一次将pop的元素的 32 * */ 33 bool pop(int *n) { 34 if(isEmpty()) return false; 35 *n=array[tail]; 36 tail=(tail+1)%(capability+1); 37 length--; 38 return true; 39 } 40 41 void showStack() { 42 int i=tail; 43 int temp=length; 44 printf("\nnew path\n"); 45 while(temp>0) { 46 printf("%d, ",array[i++]); 47 temp--; 48 } 49 } 50 }; 51 52 53 class MinStack { 54 private: 55 MyStack *mainStack; 56 MyStack *assiStack; 57 int curMin; 58 public: 59 MinStack(): mainStack(new MyStack()),assiStack(new MyStack()),curMin(0) {} 60 /** 61 * 仅当出现新的最小元素时,才将前一个最小元素压入assiStack 62 * */ 63 bool push(int n) { 64 if(mainStack->push(n)) { 65 if(n<curMin) { 66 assiStack->push(curMin); 67 curMin=n; 68 } 69 return true; 70 } 71 return false; 72 } 73 /** 74 * 仅当mianStack的pop元素等于curMin时,才从assiStack中新pop出一个元素 75 * */ 76 bool pop(int *n) { 77 if(mainStack->pop(n)) { 78 if(*n == curMin) { 79 int *temp; 80 assiStack->pop(temp); 81 curMin=*temp; 82 } 83 return true; 84 } 85 return false; 86 } 87 int min() { 88 return curMin; 89 } 90 };