两个看似简单的面试题

Sodier 2008-10-08 02:01:22
1.给定一个单链链表(节点域只包括指向下一个的指针和key value),找出从链尾倒数的第k个元素,要求尽可能高效
2.给定一个32bit的数值,如果输出比特位反转后的值,如对于4bit的二进制值1011,翻转后为1101。要求复杂度O(lgn),n
为比特位数
...全文
480 31 打赏 收藏 转发到动态 举报
写回复
用AI写文章
31 条回复
切换为时间正序
请发表友善的回复…
发表回复
runfriends 2008-10-10
  • 打赏
  • 举报
回复
第二个问题可做如下解答

int convert_32bit(int n)
{
int i,j,k,ret=0,m=0x1;
for(i=1;i<=16,i*=2)
{
k=(n>>i)&m;//把高i位移到低位
j=m|n;
k^=j;
j^=k;
k^=j;//位异或运算,把k和n的值交换,实际交换的是n的低i位。
m=(m<<i)|m;
ret=(ret<<(i*2))|((k<<i)|j);
}
return ret;//右移位低位置0,与n位或
}
1 2 4 8 16
O(5*7)
boxer_tony 2008-10-10
  • 打赏
  • 举报
回复
不知第一题的高效指的是时间效率还是包括空间效率?

如果两者都包括,那么1楼确实是很好的算法,时间复杂度是f(n)=2n-k;如果只是时间效率的话,那么可以损失空间的话可以达到f(n)=n的时间复杂度。
lyllm_117228 2008-10-10
  • 打赏
  • 举报
回复
我认为一楼的答案即简洁又高效
swf028 2008-10-10
  • 打赏
  • 举报
回复
参考8楼的思想,完成的程序.
有什么问题,大家多提下!

/////////////////////////////////////////////////////////////////////

struct node

{

int data;

node *next;

};



node *findK(node *head,int k)

{

node *p1,*p2,*p3;

int i,tmpk=1,scancount;

if (head==NULL) return NULL;



p1=head;

p2=p1;

scancount=k; //可K太小的话可以改大

while((p1=p1->next)!=NULL)

{

if (tmpk++==scancount)

{

tmpk=1;

p3=p2;

p2=p1;

}

}

if (tmpk<k)

{

for(i=0;i<tmpk+1;i++)

p3=p3->next;

return p3;

}

else if (tmpk>k)

{

for(i=0;i<tmpk-k+1;i++)

p2=p2->next;

return p2;

}

else return p2;



}

/////////////////////////////////////////////////////////////////////



int main(int argc, char* argv[])

{



node *head=new node;

head->data=1;

head->next=NULL;

node *node1=head;

for (int i=2;i<100;i++)

{

node1->next=new node;

node1->next->data=i;

node1=node1->next;

}

node1->next=NULL;

node *ret=findK(head,1);

cout<<ret->data<<endl;
}
glacier3d 2008-10-10
  • 打赏
  • 举报
回复
第二个算法在FFT里就有用哎!很实用啊!
suwein 2008-10-10
  • 打赏
  • 举报
回复
第一题程序员面试宝典里有详细介绍
suwein 2008-10-09
  • 打赏
  • 举报
回复
19楼的解法复杂度O(nlogn),你这样的话交换太多次了,还不如直接第i位和n+1-i位直接交换,每两个位只需要进行1次交换操作,O(n)
如果基于交换的话绝对不会低于O(n),因为每位都得进行交换才能到达它应该待的位置
suwein 2008-10-09
  • 打赏
  • 举报
回复
18楼给的结果是m+n=2^32-1,不符合要求啊
test4ever 2008-10-09
  • 打赏
  • 举报
回复
2题
依照题目意图

使用分治法

1.首先 将高n/2位与低n/2位交换

2.然后分治处理高n/2位,和低n/2位

3.分治中的原子操作是将x位数,其高x/2位于低x/2位交换

最终算法的时间复杂度为O(lgn)
apollofsc2008 2008-10-09
  • 打赏
  • 举报
回复
阿2果然是牛人啊,实在是佩服
第二个题看来好半天才看懂啊
deng2000 2008-10-09
  • 打赏
  • 举报
回复
抱歉,我在18楼的解答误解题意了,此"反转"非彼"反转"。谢谢指正。
suwein 2008-10-09
  • 打赏
  • 举报
回复
n^FFFF FFFF只是各位取非吧
adrian_yang84 2008-10-09
  • 打赏
  • 举报
回复
18楼的同学提醒了我,可以用异或:n︿0xFFFFFFFF
deng2000 2008-10-09
  • 打赏
  • 举报
回复
第二题的一个简便做法是利用补码:
unsigned int reverse_32bit(unsigned int n)
{
int k = n;
k = -k - 1;
unsigned int m = k;
return m;
}

另:我觉得题目的说法“要求复杂度O(lgn),n 为比特位数”有问题. 在此题中比特位数就是一个常数32, 怎么能以它规定复杂度?
oo 2008-10-08
  • 打赏
  • 举报
回复
第一题:
用三个指针p1,p2,p3
p1,p2,p3先都指向head

1,先p1跑M步(M可以是k,如果k比较小,M可以是一个比k大的值),p2设置为p1
2,p1继续跑M步,如果p1没有到链表的尾,则p3设置为p2,p2设置为p1,继续第二步;
如果p1到了链表的尾,因为p1移动时记录了移动步数,所以从p3开始移动就可以到指定的节点。

这个方法如果链表比较长时比两个指针同时移动一步效率要高一些。
currenttt 2008-10-08
  • 打赏
  • 举报
回复
2楼的算法很赞……
zsxcn 2008-10-08
  • 打赏
  • 举报
回复
mark
viqbgee 2008-10-08
  • 打赏
  • 举报
回复
我认为一楼的答案即简洁又高效
wonture 2008-10-08
  • 打赏
  • 举报
回复
1楼高啊
DongloveRen 2008-10-08
  • 打赏
  • 举报
回复
学习
加载更多回复(11)

33,008

社区成员

发帖
与我相关
我的任务
社区描述
数据结构与算法相关内容讨论专区
社区管理员
  • 数据结构与算法社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧