题意:在完全二叉树中,给两个结点的位置,求出它们最近的公共祖先(lca),输入为十六进制,输出为十六进制。
思路:表面是lca,实际是二进制的题目。比如5和9它们的lca是2。5的二进制101、9的二进制1001;它们最长公共前缀是10,也就是2。再加上16进制和2进制可以直接换算,所以我们出一下边角问题就可以直接得到lca。复杂度就是输入数据的长度。
代码:我写了个贼暴力的解法。慢慢继续学习更优解法吧。
#include<bits/stdc++.h>
using namespace std;
int a[1000],b[1000],a1[4000],b1[4000],c[4000];
int main()
{
int t,i,j,k,temp;
string str1,str2;
cin>>t;
while(t--)
{
memset(a,0,sizeof(a));
memset(b,0,sizeof(b));
memset(a1,0,sizeof(a1));
memset(b1,0,sizeof(b1));
memset(c,0,sizeof(c));
cin>>str1>>str2;
int len1=str1.size(),len2=str2.size();
for(i=0;i<len1;i++)//字符串存到数字数组里,方便进制转换
{
if(str1[i]>='a'&&str1[i]<='f')
a[i]=(str1[i]-'a')+10;
else if(str1[i]>='0'&&str1[i]<='9')
a[i]=int(str1[i]-'0');
}
for(i=0;i<len2;i++)
{
if(str2[i]>='a'&&str2[i]<='f')
b[i]=(str2[i]-'a')+10;
else if(str2[i]>='0'&&str2[i]<='9')
b[i]=int(str2[i]-'0');
}
for(i=0;i<len1;i++)//16进制转二进制
{
j=(i+1)*4;
temp=0;
while(a[i]!=0)
{
a1[j]=a[i]%2;
a[i]=a[i]/2;
j--;
temp++;
}
while(temp<4)
{
a1[j]=0;
j--;
temp++;
}
}
for(i=0;i<len2;i++)
{
j=(i+1)*4;
temp=0;
while(b[i]!=0)
{
b1[j]=b[i]%2;
b[i]=b[i]/2;
j--;
temp++;
}
while(temp<4)
{
b1[j]=0;
j--;
temp++;
}
}
len1=len1*4,len2=len2*4;
k=0;
i=1,j=1;
//存最长公共前缀
while(a1[i]==0)
i++;
while(b1[j]==0)
j++;
for(;i<=len1&&j<=len2;i++,j++)
{
if(a1[i]==b1[j])
{
c[k]=a1[i];
k++;
}
else
break;
}
//转十六进制
int num=0,f=0;
char ch[1000],sh='a';
for(i=k-1;i>=0;)
{
num=0;
temp=4;
while(temp--)
{
num+=c[i]*pow(2,3-temp);
i--;
}
if(num>=10)
ch[f]=sh+(num-10);
else
ch[f]=num+48;
f++;
}
//输出数据
for(i=f-1;i>=0;i--)
cout<<ch[i];
cout<<endl;
}
}