您的位置:首页 > 其它

2015小米在线笔试题

2015-04-25 10:31 225 查看
1、问题:输入两个32位int型数,求其他们二进制位有多少不相同。

思路:对输入的两个数m,n进行异或操作结果为a,a的二进制中有多少位为1就是所求结果,

让a分别与32个只有一位为1其它是0的int数进行&操作若不为0就可以判断这位为1.

代码:

#include <iostream>
#include <algorithm>
#include <cstring>

using namespace std;

int t[32] = {0x00000001, 0x00000002, 0x00000004, 0x00000008,
             0x00000010, 0x00000020, 0x00000040, 0x00000080,
			 0x00000100, 0x00000200, 0x00000400, 0x00000800,
			 0x00001000, 0x00002000, 0x00004000, 0x00008000,
			 0x00010000, 0x00020000, 0x00040000, 0x00080000,
			 0x00100000, 0x00200000, 0x00400000, 0x00800000,
			 0x01000000, 0x02000000, 0x04000000, 0x08000000,
			 0x10000000, 0x20000000, 0x40000000, 0x80000000};

int main()
{
	int m, n;
	int a;
	cin>>m>>n;
	a = m^n;
	//cout << a << endl;
	int oneNum = 0;
	for(int i=0;i<32;++i)
	{
		if((a&t[i])!=0)
		{
			oneNum++;
		}
	}
	cout << oneNum << endl;
	return 0;
}


找到一种新方法:

#include <iostream>
#include <algorithm>
#include <cstring>

using namespace std;

int main()
{
	int m, n;
	int a;
	cin>>m>>n;
	a = m^n;
	int oneNum = 0;
	while(a)
	{
		oneNum++;
		a = a&(a-1);
	}
	cout << oneNum << endl;
	return 0;
}


2、问题:股市股票买卖,共有n天的股市价格情况,p[i]代表第i天的股市价格,你可以至多买卖两次股票(每次买股票时手中是没有股票的),问如何买卖收益才最大。
思路:m[i][j]代表从第i天到第j天股票价格的最低值,m[i][j]=min(m[i][j-1],p[j])

分两种情况:(1)买卖0次或1次,maxVal = p[i]-m[1][i-1];

(2)买卖两次v[i][j]代表分别在第i天和第j天卖出时收益最大值,则v[i][j] = p[i]-m[1][i-1]+p[j]-m[i+1][j-1],求v[i][j]中最大值。

代码:

#include <iostream>
#include <algorithm>
#include <cstring>

using namespace std;

const int NUM = 100;

int m[NUM][NUM];
int p[NUM];
int v[NUM][NUM];

int main()
{
	int n;
	while(cin>>n)
	{
	    memset(m, 0 , sizeof(m));
     	memset(p, 0, sizeof(p));
    	memset(v, 0, sizeof(v));
	    for(int i=1;i<=n;++i)
	    {
		     cin>>p[i];
		     m[i][i] = p[i];
	    }
	
	    for(int i=1; i<n; ++i)
	    {
		    for(int j=i+1; j<=n; ++j)
	     	{
		    	m[i][j] = min(m[i][j-1], p[j]);
	    	}
	    }
	
	    int maxVal = 0;
	
    	for(int i=2; i<=n; ++i)
    	{
    		if(p[i]-m[1][i-1]>maxVal)
    		{
    			maxVal = p[i]-m[1][i-1];
    		}
    	}
	
    	for(int i=2; i<=n-2; ++i)
    	{
    		for(int j=i+2; j<=n; ++j)
    		{
    			if(p[i]-m[1][i-1]>0)
    			{
    				v[i][j] += p[i]-m[1][i-1];
    			}
    			if(p[j]-m[i+1][j-1])
    			{
    				v[i][j] += p[j]-m[i+1][j-1];
    			}
    			if(v[i][j]>maxVal)
    			{
    				maxVal = v[i][j];
    			}
    		}
    	}	
    	cout << maxVal << endl;
	}
	return 0;
}


3、问题:git是一种分布式代码管理工具,git通过树的形式记录文件的更改历史,比如:

base'<--base<--A<--A'

^

| --- B<--B'

小米工程师常常需要寻找两个分支最近的分割点,即base.假设git 树是多叉树,请实现一个算法,计算git树上任意两点的最近分割点。

(假设git树节点数为n,用邻接矩阵的形式表示git树:字符串数组matrix包含n个字符串,每个字符串由字符'0'或'1'组成,长度为n。matrix[i][j]=='1'当且仅当git树种第i个和第j个节点有连接。节点0为git树的根节点。)


输入例子:

[01011,10100,01000,10000,10000],1,2



输出例子:

1

思路:使用最短路径,存储下根节点到目标节点的路径,比较两条路径分离点。


int getSplitNode(vector<string> matrix, int indexA, int indexB)
{
	bool flag[101];
	int n = matrix.size();
	int path[101][101];
	int dist[101];
	int prev[101];
	stack<int> A, B;
	
	int NOPATH = 10000;
	
	for(int i=0; i<n; ++i)
	{
		for(int j=i; j<n; ++j)
		{
			if(matrix[i][j]=='0')
			{
				path[i][j] = NOPATH;
				path[j][i] = NOPATH;
			}
			else
			{
				path[i][j] = 1;
				path[j][i] = 1;
			}
		}
	}

	for(int i=1; i<n; ++i)
	{
		dist[i] = path[0][i];
		flag[i] = false;
		if(dist[i]<NOPATH)
		{
			prev[i] = 0;
		}
		else
		{
			prev[i] = -1;
		}
	}
	prev[0] = -1;
	dist[0] = 0;
	flag[0] = true;
	
	for(int i=1; i<n; ++i)
    {
        int tmp = NOPATH;
        int u = 0;

        for(int j=1; j<n; ++j)
            if((!flag[j]) && dist[j]<tmp)
            {
                u = j;            
                tmp = dist[j];
            }
        flag[u] = 1;   
  
        for(int j=1; j<n; ++j)
            if((!flag[j]) && path[u][j]<NOPATH)
            {
                int newdist = dist[u] + path[u][j];
                if(newdist < dist[j])
                {
                    dist[j] = newdist;
                    prev[j] = u;
                }
            }
    }
    

    while(indexA!=-1)
    {
    	A.push(indexA);
    	indexA = prev[indexA];
    }
  
    while(indexB!=-1)
    {
    	B.push(indexB);
    	indexB = prev[indexB];	
    }
    
    int result = -1;
    while(!A.empty()&&!B.empty())
    {
    	
    	int ta = A.top();
    	A.pop();
    	int tb = B.top();
    	B.pop();
    	if(ta==tb)
    	{
    		result = ta;
    	}
    	else
    	{
    		break;
    	}
    }
  
    return result;
}
另一种方法:使用深度搜索记录下每个节点的父节点及深度然后如下搜索(dep为深度信息,fa为父节点)

int a = indexA, b = indexB;

while ( dep[a] > dep[b] ) {

a = fa[a];

}

while ( dep[a] < dep[b] ) {

b = fa[b];

}

while ( a != b ) {

a = fa[a];

b = fa[b];

}

以上方法仅是自己的思路,想来还有更好更快的方法希望可以看到。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: