出题:输入一个整数数组,判断该数组是否符合一个二元查找树的后序遍历(给定整数数组,判定其是否满足某二元查找树的后序遍历);
分析:利用后序遍历对应到二元查找树的性质(序列最后一个元素必定是根节点,从左向右第一个比根节点大的元素开始直到根节点之前的所有元素必定在右子树,之前的所有元素必定在左子树);
解题:
1 bool PostOrderCheck(int *array, int i, int j) { 2 /** 3 * 如快速排序一样,解决小子文件 4 * */ 5 if(j-i+1 == 3) { 6 if(array[i]<=array[i+2] && array[i+2]<=array[i+1]) 7 return true; 8 else 9 return false; 10 } else if(i-i+1 == 2) { 11 if(array[i]<=array[i+1] || array[i]>=array[i+1]) 12 return true; 13 else 14 return false; 15 } 16 17 int left=i, right=j-1; 18 /** 19 * 一共有四种情况:指针交叉后跳出,指针未交叉即跳出,left到达最右边,right到达最左边 20 * 如果第二种情况成立则判定必定失败 21 * */ 22 while(left<j) { 23 if(array[left]>array[j]) 24 break; 25 left++; 26 } 27 while(right>=i) { 28 if(array[right]<array[j]) 29 break; 30 right--; 31 } 32 /** 33 * 两种特殊情况:只有左子树或者只有右子树的递归 34 * */ 35 if(left==j || right<i) 36 return PostOrderCheck(array, i, j-1); 37 /** 38 * 另外两种跳出情况,break,此时left和right不可能重合 39 * */ 40 if(left>right) { 41 /** 42 * 如果left比right大,说明成功交叉 43 * */ 44 return PostOrderCheck(array, i, right) || PostOrderCheck(array, left, j-1); 45 } else { 46 /** 47 * 如果left比right小,说明左子树中有元素比根节点大,或者右子树中有元素比根节点小 48 * */ 49 return false; 50 } 51 }
出题:输入一个英文句子,其中的单词以空格符号隔开;要求翻转句子中单词的顺序,但是单词内字符顺序不变(简单起见,标点符号和普通字母一样处理);
分析:两次翻转,全局翻转(针对所有字符)和局部翻转(针对两个空格符之间的字符)
解题:
1 /** 2 * 借用之前已经实现的全局翻转函数reverse 3 * */ 4 void reverse(char* target, int length) { 5 char temp; 6 int i; 7 for(i=0;i<length/2;i++) { 8 temp=*(target+i); 9 *(target+i)=*(target+(length-i-1)); 10 *(target+(length-i-1))=temp; 11 } 12 } 13 void DoubleTransfer(char *target, int length) { 14 /** 15 * 首先进行全局翻转,得到!tneduts a ma i 16 * */ 17 reverse(target, length); 18 char *part=NULL; 19 int partLength; 20 /** 21 * 然后进行局部翻转,从第一个非空格符的字符开始计算 22 * 子子序列的长度,直到第一个空格符号结束,然后 23 * 调用reverse进行局部翻转,最后进入下一个iteration 24 * */ 25 for(int i=0;i<length;i++) { 26 partLength=0; 27 while(target[i] == ' ' && i<length) i++; 28 part=target+i; 29 while(target[i] != ' ' && i<length) { 30 i++; 31 partLength++; 32 } 33 reverse(part, partLength); 34 } 35 }