T公司的一道机试题
题目:
五笔的编码范围是a ~ y的25个字母,从1位到4位的编码,如果我们把五笔的编码按字典序排序,形成一个数组如下:
a, aa, aaa, aaaa, aaab, aaac, … …, b, ba, baa, baaa, baab, baac … …, yyyw, yyyx, yyyy
其中a的Index为0,aa的Index为1,aaa的Index为2,以此类推。
1)编写一个函数,输入是任意一个编码,比如baca,输出这个编码对应的Index;
2)编写一个函数,输入是任意一个Index,比如12345,输出这个Index对应的编码。
思考:
这个是字典序计数,和五笔没毛的关系。
看到后不禁想到二十六进制数,但稍微看一下就知道不是,a和b之间的距离很远,不是1,不过似乎还有某种二十六进制数的影子.
显然编码与index之间是一一映射的关系,那么肯定有个函数表达这个映射,于是思考这个函数表达式。遗憾的是,思考了很久,也没找到公式。
编码的长度分别是1,2,3,4,而且没有遗漏某个编码。长度可以用某种层次关系来表达,在上一次的基础上增加一位得到更长的编码。合适的数据结构是:树。
于是,豁然开朗。构建树如下:
写了下实现,C#的,用孩子兄弟链表表示树。做一次先根遍历得到所有结点的序号。不知道有没有人能给出映射函数??
字典序计数
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
namespace 字典序計數
{
class Node
{
/// <summary>
/// 字符
/// </summary>
public String symbol;
/// <summary>
/// 序號
/// </summary>
public int index;
/// <summary>
/// 孩子節點
/// </summary>
public Node child;
/// <summary>
/// 兄弟節點
/// </summary>
public Node brother;
}
class Tree
{
public static String [] Dict = {"a","b","c","d","e","f","g","h","i","j","k","l",
"m","n","o","p","q","r","s","t","u","v","w","x","y"};
public Node root;
public Tree()
{
root = new Node();
root.symbol="";
root.index = -1;
root.child = null;
root.brother = null;
}
public void GenerateTree(Node root,int height)
{
if(height==5)
{
return;
}
Node child = new Node();
child.symbol = Dict[0];
root.child = child;
GenerateTree(root.child, height + 1);
Node temp = child;
for (int i = 1; i < Dict.Length; i++)
{
Node brother = new Node();
brother.symbol=Dict[i];
GenerateTree(brother, height + 1);
temp.brother = brother;
temp = brother;
}
}
public void TraverseTree(Node root, int index, StreamWriter sw,String result)
{
if (root != null)
{
root.index = index;
sw.WriteLine(result + root.symbol + ",index=" + root.index);
//Console.WriteLine(result+root.symbol + ",index="+root.index);
TraverseTree(root.child, root.index+1,sw,result + root.symbol);
if (root.child == null)
{
TraverseTree(root.brother, root.index + 1, sw, result);
}else
{
Node ctemp = root.child;
Node btemp = root.brother;
while (ctemp != null)
{
btemp = ctemp.brother;
while (btemp.brother != null)
{
btemp = btemp.brother;
}
ctemp = btemp.child;
}
TraverseTree(root.brother, btemp.index + 1, sw, result);
}
}
}
public int GetIndex(String code)
{
Node temp = root.child,goal=root.child;
int index = -1;
int len = code.Length;
int i = 0;
for (i = 0; i < len; i++)
{
if (temp.symbol.CompareTo(code[i].ToString()) == 0)
{
goal = temp;
temp = temp.child;
continue;
//i++;
}
if (temp.symbol.CompareTo(code[i].ToString()) < 0)
{
while (temp.symbol.CompareTo(code[i].ToString()) != 0)
{
temp = temp.brother;
}
goal = temp;
temp = temp.child;
}
}
return goal.index;
}
public String GetCode(int index)
{
Node temp = root,small=root.child,big=root.child;
String result = "";
while (temp.index != index)
{
while (temp!=null&&temp.index < index)
{
small = temp;
temp = temp.brother;
}
if(temp==null)
{
result += small.symbol;
temp = small.child;
if (temp.index == index)
{
result += temp.symbol;
break;
}
continue;
}
if (temp.index != index)
{
result += small.symbol;
big = temp;
if (small.child != null)
{
temp = small.child;
if(temp.index==index)
{
result += temp.symbol;
break;
}
}
else
{
temp = small;
}
}else
{
result += temp.symbol;
break;
}
}
return result;
}
}
class Program
{
static void Main(string[] args)
{
Tree T = new Tree();
T.GenerateTree(T.root, 1);
FileStream fs = new FileStream("result.txt", FileMode.Create);
StreamWriter sw = new StreamWriter(fs);
int index = -1;
T.TraverseTree(T.root,index, sw,"");
sw.Flush();
sw.Close();
String goal = "";
while ((goal = Console.ReadLine())!="$")
{
index = T.GetIndex(goal);
Console.WriteLine(index);
Console.WriteLine(T.GetCode(index));
}
Console.WriteLine(25 + 25 * 25 + 25 * 25 * 25 + 25 * 25 * 25 * 25);
}
}
}