小米 2016届实习生招聘笔试

第一部分:

三道编程题。

1.两个整数的二进制表示中,求不同位数的个数。

   比如输入1和2,01和10不同位数为2,故输出为2.

2.选择买入卖出股票的最大收益,要求交易次数为两次,但是第二次买入必须在第一次卖出的时间节点之后。

    比如{3,8,5,1,7,8},最大收益为8-3加上8-1,等于12.

3.求linux文件目录中两个分支的最近父节点。

   root->0->1->2

              |

             3->4

   此时1和3的最近父节点为0,2和4的最近父节点为0,1和2的最近父节点为1。

   输入两个节点indexA和indexB,找出最近连接点,即找出最近父节点。


第二部分:

四道主观题,根据你投的岗位进行选择性答题,客户端、前端、后台等。

由于我投的岗位是客户端,所以只做了第一题和第四题

1.客户端

   Bundle是什么?Bundle和Java中Map的区别?Android中为什么不用Map而是使用Bundle传递数据?

2.前端

3.后台

4.编程题

   在一个整形数组N中,寻找和为M的两个数,要求复杂度低。如有返回两数,没有返回-1.



第一部分解答

1.基本思想:两数先异或运算,把位数不同的位全部转成1,最后求出二进制结果中1的个数即可。

#include <iostream>
using namespace std;

int cal(int a, int b)  
{  
    int M = a ^ b;  
    int num = 0;  
    while(M)  
    {  
        M &= (M-1);  
        num++;  
    }  
    return num;  
} 

int main()
{
	int a,b;
	cin>>a>>b;
	cout<<cal(a,b)<<endl;

	return 0;
}


2.基本思想:

http://blog.csdn.net/lu597203933/article/details/44998499
此题就是选择买入卖出股票的最大收益,对于第i天卖出的最大收益即为第i天的股市价格减去[0,i-1]天内的最小股市价格,当第i天的股市价格比漆面最低股市价格还低,则更新最低股市价格。然后取最大的股市收益,为DP问题。 用profit[i]表示第i天的收益,则minBuyPrice = min(minBuyPrice, prices[i]),并且profit[i] = prices[i]-minBuyPrice.   然后取profit中的最大值。

动态规划,用两个数组,第一个数组f[i]用来表示在[0,i]内进行买入卖出的最大收益,用g[i]表示在[i,n-1]内进行买入卖出的最大收益。然后最大收益即为max(f[i]+g[i])。

#include <iostream>
using namespace std;

#define max(a,b) (((a)>(b))?(a):(b))
#define min(a,b) (((a)<(b))?(a):(b))

int maxProfit(int prices[], int n)
{
	int i,minP,maxP,ans=0;
    int *f=(int *)malloc(sizeof(int)*n);// 表示在[0,i]内进行买入卖出所能获得的最大profit
	int *g=(int *)malloc(sizeof(int)*n);// 表示在[i,n-1]内进行买入卖出所能获得的最大profit  结果就为max(f1[i]+f2[i])  
	if(n<2)
		return 0;
	else
	{
		f[0]=0;
		g[n-1]=0;
		for(i=1,minP=prices[0];i<n;i++)
		{
			minP=min(minP,prices[i]);
			f[i]=max(f[i-1],prices[i]-minP);			
		}
		for(i=n-2,maxP=prices[n-1];i>=0;--i)
		{
			maxP=max(maxP,prices[i]);
			g[i]=max(g[i+1],maxP-prices[i]);			
		}
	}
	for(i=0;i<n;i++)
	{
		ans=max(ans,f[i]+g[i]);
	}
	return ans;
}

int main()
{
	int prices[6]={3,8,5,1,7,8};
	cout<<maxProfit(prices, 6)<<endl;

	return 0;
}


3.基本思想:

将连接关系转换为二维数组存储。如A->B有连接则为1,无连接则为0.

indexA和indexB直接相连,则最近父节点为indexA和indexB中较小的一个,

indexA和indexB不直接连接,找出都连接indexA和indexB的节点即为最近父节点。

    0 1 2 3 4

0  0 1 0 1 1

1  1 0 1 0 0

2  0 1 0 0 0

3  1 0 0 0 0

4  1 0 0 0 0


连接关系如下:

4

|

0——>1——>2

|

3


方法一:递归遍历

#include <iostream>
using namespace std;

int find(int a[][5],int indexA,int indexB)//假设二维数组长宽都为5
{
	int result;
	if(indexA==0 || indexB==0)
	{
		result=0;
		return result;
	}
	else if(a[indexA][indexB]==1)//直接相连
	{
		if(indexA>=indexB)
			result=indexB;
		else
			result=indexA;
		return result;
	}
	else if(a[indexA][indexB]==0)//不直接相连
	{
		for(int i=0;i<5;i++)
		{
			if(a[i][indexA]==1 && a[i][indexB]==1)
			{
				result=i;
				return result;
			}
			else if(a[i][indexA]==1)
				find(a,i,indexB);//递归
			else if(a[i][indexB]==1)
				find(a,indexA,i);
		}	
	}
}

int main()
{
	int a[5][5]={
		0,1,0,1,1,
		1,0,1,0,0,
		0,1,0,0,0,
		1,0,0,0,0,
		1,0,0,0,0};

	cout<<find(a,1,2)<<endl;
	cout<<find(a,3,4)<<endl;
	cout<<find(a,0,4)<<endl;
	cout<<find(a,2,4)<<endl;

	return 0;
}


方法二:数组存储

基本思想:

不同数组A和B分别存储indexA和indexB的所有父节点,然后从头到尾遍历A和B,找到A和B的第一个相同点,就是最近父节点

    #include <iostream>  
    using namespace std;  
      
    int find(int a[][5],int indexA,int indexB)//假设二维数组长宽都为5  
    {  
        int result;  
        int A[5]={0}; //存储indexA和indexB的所有父节点
		int B[5]={0};
		
		int xA=indexA;
		int xB=indexB;

		int kA=0,kB=0;
		A[kA++]=indexA;
		B[kB++]=indexB;
		for(int k=0;k<5;k++)
		{
			if(a[k][xA]==1 && k<=xA)
			{
				A[kA++]=k;
				xA=k;
			}
			if(a[k][xB]==1 && k<=xB)
			{
				B[kB++]=k;
				xB=k;
			}
		}

		//此时数组A和B中存储的就是indexA和indexB的所有父节点,下标从大到小
		//要找indexA和indexB的最近父节点,从头开始遍历数组A和B,找到最小的相同点就是答案

//		for(int kk=0;kk<5;kk++)
//		{
//			cout<<A[kk]<<" "<<B[kk]<<endl;
//		}

		int i=0,j=0;
		while(i<5 && j<5)
		{
			if(A[i]>B[j])
				i++;
			else if(A[i]<B[j])
				j++;
			else
			{
				result=A[i];
				break;
			}
		}

		return result;
    }  
      
    int main()  
    {  
        int a[5][5]={  
            0,1,0,1,1,  
            1,0,1,0,0,  
            0,1,0,0,0,  
            1,0,0,0,0,  
            1,0,0,0,0};  
      
        cout<<find(a,1,2)<<endl;//1
        cout<<find(a,3,4)<<endl;//0  
        cout<<find(a,0,4)<<endl;//0
        cout<<find(a,2,4)<<endl;//0
      
        return 0;  
    }  



第二部分解答

1..Bundle格式的文件是Unix/Linux系统中的一种可执行文件。用户可以在终端中使用./***(文件名).bundle命令使其运行。必要时需要使用sudo执行以提供超级用户权限,并且需要提供管理员密码。

    Bundle类是一个key-value对,“A mapping from String values to various Parcelable types.”用于Android的Activity之间传递数据的类。

    Bundle和Map区别:

    Bundle类用作携带数据,它类似于Map,用于存放key-value名值对形式的值。

    相对于Map,它提供了各种常用类型的putXxx()/getXxx()方法,如:putString()/getString()和

    putInt()/getInt()。Bundle的内部实际上是使用了HashMap类型的变量来存储putXxx()方法放入的值。

   

   Android开发默认情况下,通过Bundle bundle=new Bundle();传递值是不能直接传递map对象的,解决办法:

   第一步:封装自己的map,实现序列化即可   

/**
 * 序列化map供Bundle传递map使用
 * Created  on 13-12-9.
 */
public class SerializableMap implements Serializable {
 
    private Map<String,Object> map;
 
    public Map<String, Object> getMap() {
        return map;
    }
 
    public void setMap(Map<String, Object> map) {
        this.map = map;
    }
}

第二步:传递数据:

Intent intent=new Intent(ListViewActivity.this,UpdateWatchActivity.class);
                                //传递数据
                                final SerializableMap myMap=new SerializableMap();
                                myMap.setMap(map);//将map数据添加到封装的myMap<span></span>中
                                Bundle bundle=new Bundle();
                                bundle.putSerializable("map", myMap);
                                intent.putExtras(bundle);

第三步:接收数据:

Bundle bundle = getIntent().getExtras();
        SerializableMap serializableMap = (SerializableMap) bundle.get("map");

到此数据就能在通过map传递和使用了。

   

2.网上这道题泛滥,求数组N中和为M的两个值,就不给代码了。

(1)如果扫两遍,则时间复杂度为O(n^2);

(2)先排序,后二分查找,排序,快排或者堆排O(nlogn),

        然后对于每个数i,在排好序的数组中用二分查找找M-i,复杂度O(nlogn)

        相加最后时间复杂度还是O(nlogn).

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值