说说一个简单的面试题

过节了终于有时间写写东西了,有些东西不记录下来就会一点点忘掉。

前几天去面试,有一道题我回答的不太令自己满意,回来之后思索了一下,又想到了一些东西,记录一下。

简单问题?

题目就是简单的反转单向链表。

我很快给出了一段代码:

void reverse_chain(Node *h)
{
    if(!h || !h->next) return ;
    Node *previous = NULL,
         *current  = h,
         *next     = h->next;
    while(next) {
        current->next = previous;
        previous = current;
        current  = next;
        next     = next->next;
    }
    current->next = previous;
    h->next = NULL;
}

这段代码显然是有问题的,它没有返回反转后的链表的头指针,只需在最后加上一句 return current; 即可。比较理想的代码如下所示:

Node * reverse_chain(Node *h)
{
    if(!h || !h->next) return h;
    Node *previous = NULL,
         *current  = h,
         *next     = h->next;
    while(next) {
        current->next = previous;
        previous = current;
        current  = next;
        next     = next->next;
    }
    current->next = previous;
    h->next = NULL;
    return current;
}

复杂问题?

接下来,面试官问了我一个问题:可不可以只使用两个指针,完成单向链表的反转?

我思索了一段时间,认为不能够只使用两个指针完成单向链表的反转。理由是这样的,反转单向链表的过程,需要将当前节点指向前一个节点,这里需要两个指针,因为前一个节点的指针已经指向了更前一个节点;完成这一动作后,需要继续处理下面的节点,因此还需要能够索引到下一个节点;这样,一共需要三个指针。(我还特意向面试官询问了,是否考虑在调用栈上保存信息的情况,即使用递归算法)

其实这个答案是正确的。但是面试官一再强调,一定可以只使用两个指针完成单向链表的反转。于是我向面试官请求一些提示。

面试官给出了这样的提示:如果像这样每次处理完一个节点后向后移动一个节点继续处理,则需要三个指针;如果不是采用向后移动的方式,是否有可能采用更少的指针?譬如说每次都将下一个节点插入到链表头部。

每次将当前节点从链表中取下插入到链表头部似乎仍然需要3个指针:一个指向表头,一个指向当前节点,一个指向当前节点的上一个节点。

图表1

图1:将当前节点插入到链表头反转单向链表示意图。

 

最后终于想到了利用原来链表头的next域来存储Previous节点的方法。

面试官友善的说道,最终原来链表头的next域是要指向Nil的,因此利用原来链表头的next域进行存储是一种很自然的想法。

无意义问题?

说实在的,这个链表反转的方法实际上还是用了3个指针,可以说一开始我就没走到面试官所希望我想到的东西的道路上。实际上,我内心深处还是颇为不赞同这样一种方式的,因为这个反转链表的方法有效率上的问题:即如何快速的访问原来链表头的next域?如果为此引入一个指针的话,就实际上需要4个指针,比原来的方法还要多出来一个;否则就需要遍历O(n)的链表才能够发现原来链表头的next域,时间复杂度上得不偿失。

并且,实际上使用了3个指针还是2个指针,在C程序编译完后,实际上只是对应着使用了3个寄存器还是2个寄存器,本质上并没有时空性能上的提升,还为此付出了额外的代码复杂度,实在是没有什么意义。

所以?

所以其实这个问题就是没什么意义,面试官对于问题的描述和引导也做得不好,但是对于这一问题所带来的新的思路,确实令我思索了很久。有的时候,我就是在做一些没有意义的事情,但是探索过程本身,却能给我带来很大的乐趣和价值。

Technorati 标签: 面试, C, 链表

转载于:https://www.cnblogs.com/HCOONa/archive/2012/01/24/a-simple-interview-problem.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值