腾讯2013的一道实习生笔试题

腾讯2013的一道实习生笔试题


  • 题目

    给定一个数组a[N],我们希望构造数组b[N],其中b[i]=a[0]*a[1]*...*a[N-1]/a[i]。
    在构造过程:不允许使用除法;
    要求:O(1)空间复杂度和O(n)时间复杂度;
    除遍历计数器与a[N] b[N]外,不可使用新的变量(包括栈临时变量、对空间和全局静态变量等);
    请用程序实现并简单描述。
    
  • 题目解析

    本身这个题是很容易实现的,但是加了诸多限制,就比较有意思了。
    我们一个一个来分析
    1.不能使用除法,这个好解决,只要乘的过程中不乘a[i]即可,那么整个a数组就被分成了两部分,
    一个是i位置前,一个是i位置后,注意:这个思考很关键,后面的实现都是基于它的,也可以说是
    用了一点点分治吧
    
    2.O(1)空间复杂度,没什么说的。
    
    3.O(n)时间复杂度,就是说只能一重循环,注意:只能用一重循环,
    但是没说用几次一重循环,也就是说可以多次,一次一重循环谁也做不出来。
    
    4.除遍历计数器与a[N] b[N]外,不可使用新的变量(包括栈临时变量、对空间和全局静态变量等),
    这个就厉害了,不能用变量存储值,就只能存在数组中,不能用栈临时变量,也就是不能用递归了,
    没有这个条件的话用递归和一重循环也不是很难就可以做到。
    

逻辑思维好的可以直接看代码

  • 分析过程

    这个题目我们主要是运用迭代的思想,不断更新数据,首先前面我们说了a数组被分成两部分,前一部分和后一部分;
    
    首先解决前一部分,当然是用b数组来存储结果,
    b[1] = a[0]
    b[2] = a[0]a[1]
    …
    b[i] = a[0]a[1]a[2]…a[i-1]
    通过演算我们发现b[i]都要比a[i]多一个a[i-1],那么可以写成b[i] = b[i-1] + a[i-1],至于b[0],
    就赋值1就好啦,这样我们就把前半部分解决了。这就是迭代的思想
    
    后半部分还是得用迭代的思想,我们用b[0]来存后半部分,并迭代更新,只要逆序就好了,
    看代码更直观,有了前面的铺垫相信很快就能看懂
    

/*
    以三个元素举例
*/
#include <stdio.h> 
#define N 3
int a[N] = {5,4,3}; 
int b[N];
void Translate(int a[], int b[],int n)
{
    b[0] =  1;
    for(int i = 1; i < n; i++)
    {
        b[i] = b[i-1] * a[i-1];     //b[i]保存的是a[0]一直到a[i-1]的乘积,也就是a在i位置之前所有元素的乘积 
    }
    for(int i = n-1; i > 0; i--)
    {
        b[i] *= b[0];       //b[0]存储的是a[i+1]到a[n]的乘积,也就是a在i位置之后所有元素的乘积 
        b[0] *= a[i];       //b[0]的值迭代更新  
    }
}
int main()
{
    int i;
    Translate(a,b,N);
    for(i = 0; i < N; i++)
        printf("%d ",b[i]);
    return 0;
}

参考此博客作出,上面还有两种方法

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值