面试1题解析


作者:Josunna
时间:2012年4月12日。
出处:http://blog.csdn.net/josunna
声明:版权所有,侵犯必究。如有转载,请注明出处,谢谢!


题目:有从1到n共n个数,乱序,随意去掉其中两个数,用O(n)的时间复杂度和O(1) 的空间复杂度求是哪两个数

 算法简单描述如下:
由于仅少了两个数,所以可证仅有两个链是开放的,其他的链都是闭合的。
1.标记访问过的元素
2.每次找到一个单向非闭合的链,就把它表头a[i]的下标i记录下来,并更改表头a[i]的值为表尾t。
3.最后输出记录下来的两个表尾,即是缺少的两个元素。
由1.2.保证了平均每个元素至多被访问两次。


为了简便仅举一例子说明:
为方便,考虑0到n-1这n个数
例如一共有6个数去掉了两个,3 和 5,输入为 4 2 0 1 ? ?
其中有两个链不是闭合的
a[3]=1 a[1]=2 a[2]=0 a[0]=4 a[4]=?
a[5]=?
这两个链的头的下标,即是缺少的元素

code:

/*
 * 最坏情况下时间复杂度为2n即O(n),空间复杂度为O(1) 数组的每个元素平均最多被访问两次。
 */
void find2ofnt(vector<int> &a, int &n1, int &n2){
    int n = a.size()+2;
    n1 = n-1; n2 = n-2;
    for(int i=0, t=0; i<a.size(); ++i){
        if (0>a[i]) continue;
        t=i;
        do {
            int tp=a[t]; a[t]=-1; t=tp;
        }while (0<=t && t<n-2 && t!=i);
        a[i]=t;
        if (0>t || t==i) continue;
        n-1==t ? n1=i:n2=i;
    }
}




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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值