简答题二:
逆序数组中只含有ABCD四个字母,长度为1-1024,A<B<C<D,求逆序对的对数,时间要求o(n)
思路:
该数组中因为只有ABCD四中字母,要求只遍历一次,那么反向从后往前遍历的话,每次记录每个字符出现的次数,并查看比当前字符小的字符出现多少次,即可计算出当前字符与其后面字符已有多少逆序对,以此方法累加直至第一个字符。
例题:DBBAC
分析C 出现一次
A 出现一次(但是A后面不可能有逆序对了)
B 出现一次 (BA逆序对数即为A出现的次数:1)
B 出现两次 (BA逆序对数为A出现次数:1,单此时总的逆序对已经为2了)
D (DC:1,DB:2,DA:1,D的逆序对数为4,但总的逆序对数为6了)
int SumInvertedSeq(const string &str) { int A[3] = { 0 }; int sum = 0; for (int i = str.size() - 1; i >= 0; --i) { switch (str[i]) { case 'A': ++A[0]; break; case 'B': ++A[1]; sum += A[0]; break; case 'C': ++A[2]; sum += A[0]+A[1]; break; case 'D': sum += A[0] + A[1] + A[2]; break; } } return sum; }
编程题一:
一个满二叉搜索树,节点的值按照1-n排列,输入层数,和三个节点的数值,求这三个节点的最小公共父节点的值并输出
输入 4 10 13 15
输出 12
思路:因为该二叉树是一个满的搜索树,那么画出一个数就知道了,其根节点是有规律的,最初的根节点的值为(1+2^k-1)/2,在给定的三个节点值中找出最小值和最大值,递归搜索,只需要找到最小值为其左子树最大值为其右子树的节点即为所求根节点。而其中的三个节点,中间的那个节点其实是个干扰项。
就例子而言,如图
思路清晰了后,代码就简单了;最初的调用查找中start=1,end=powbase2(k)-1
int powbase2(int n) { int res = 1; for (int i = 0; i < n; ++i) res *= 2; return res; } int FindCommonParent(int start, int end, int min, int max) { int root = (start+end) / 2; if (min == root || max == root) return root; else if (min<root && max>root) return root; else if (max < root) return FindCommonParent(start, root - 1, min, max); return FindCommonParent(root + 1, end, min, max); }
编程题二:
对于输入的16倍个字符,按照首地址00000000 16进制字母 字母 每行16个输出,一行输出后下一地址增加10,
思路:改题目中输入字符串后,按16个字符一处理,输出对应16进制通过cout<<hex控制,并没有什么其他的技巧和难题。感觉需要的是地址的加法和输出,这里我想到的是用string来存放这个首地址00000000,然后每次对她的size()-2位上加一,并且当该为为9时,下一次为A然后继续加,当为F时,档位变位0,前一位递归加一,一次类推,来改变地址字符串。我懒得很,代码已经提交,不想在写了,所以这里没有~~~