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];
}