审题:
本题需要我们将字符串按照题目要求进行递归展开,并按照后序遍历的顺序输出
思路:
方法一:递归
首先我们需要模拟一下题目的意思
其实就是第一步判断属于什么字符,然后将字符串分两半进行下一轮判断。而由于题目要求按后序遍历输出,所以我们就按照后续遍历的方式进行递归调用
疑问:我们如何判断字符串的情况?
如果我们直接遍历来判断会导致时间复杂度过高,所以我们可以采用数值判断法
假设字符串的每一个索引位置的值相加之和为0,说明字符串都为0,此时为字符'B'。
假设字符串的每一个索引位置的值相加之和等于字符串长度,说明字符串都为1,此时为字符'I'。
其他情况就为字符‘F’
递归功能:完成对应索引区间的字符串的后序遍历字符输出
解题:
#include<iostream> using namespace std; const int N = 15; int f[1 << N];//前缀和数组 int n; //dfs负责解决区间中所有字符串翻译与输出的问题 void dfs(int left, int right) {//结束条件if (left > right){return;}//判断当前串的类型char answer;int sum = f[right] - f[left - 1];if (sum == 0) answer = 'B';else if (sum == right - left + 1) answer = 'I';//sum等于串长度else answer = 'F';//按照后序遍历的方式进行if (left == right)//还剩最后一个字符,若不截断会死递归{cout << answer;return;}int mid = (left + right) / 2;dfs(left, mid); dfs(mid + 1, right);cout << answer; } int main() {cin >> n;n = (1 << n);for (int i = 1; i <= n; i++){char ch;cin >> ch;if (ch == '1') f[i] = f[i - 1] + 1;else f[i] = f[i - 1];}dfs(1, n);return 0; }
1.我们使用前缀和算法快速的求出对应字符串的sum,前缀和数组存储的是每一个字符的前缀和的值
2.结束条件:left大于right或left等于right
其中大于的情况下:说明所有字符串都遍历完了,直接返回
等于的情况:如果不截断下来会出现死循环,因为mid会等于left。这种情况只剩当前的字符没有输出,我们直接输出当前字符并返回即可
P1087 [NOIP 2004 普及组] FBI 树 - 洛谷