/ /
/ 5 6 8
2 3
2、3长度为3, 3 * 2 + 3 * 3
5、6、8长度为2
位置 |
0 |
1 |
2 |
3 |
4 |
5 |
6 |
记录 |
63 |
48 |
38 |
25 |
74 |
52 |
|
查找次数 |
1 |
3 |
1 |
1 |
2 |
4 |
冒泡排序、插入排序、归并排序和基数排序是稳定的排序算法
int a1=x+y-z; int a2=x-z+y; A、a1一定等于a2
16、找工作的季节马上就到了,很多同学去图书馆借阅《面试宝典》这本书,现在图书馆外有6名同学排队,其中3名同学要将手中的《面试宝典》还至图书馆,有3名同学希望从图书馆中可以借到《面试宝典》,若当前图书馆内已无库存《面试宝典》,要保证借书的3名同学可以借到书,请问这6位同学有多少种排队方式(180)
5、为了某项目需要,我们准备构造了一种面向对象的脚本语言,例如,对所有的整数,我们都通过Integer类型的对象来描述。在计算“1+2”时,这里的“1”,“2”和结果“3”分别为一个Integer对象。为了降低设计复杂度,我们决定让Integer对象都是只读对象,也即在计算a=a+b后,对象a引用的是一个新的对象,而非改a所指对象的值。考虑到性能问题,我们又引入两种优化方案:(1)对于数值相等的Integer对象,我们不会重复创建。例如,计算“1+1”,这里两个“1”的引用的是同一个对象——这种设计模式叫做();(2)脚本语言解析器启动时,默认创建数值范围[1,32]的32个Integer对象。现在,假设我们要计算表达式“1+2+3+…+40”,在计算过程需要创建的Integer对象个数是()。
享元模式,40。1到7以及他们的和是不用创建的,从8开始,28(是1到7的和)+8=36,36需要创建,36+9=45,45需要创建…依次类推,在加数是32之前(含32)需要创建的对象是32-8+1=25,某数+32=某数之后33至40所表示的加数也要创建,这样有8个加数 + 8个和,共有16个数需要创建,注意,加数中包含36,这个我们已经创建了,所以有25+8+8-1=40个数的对象需要创建。
加分题:
1、给定一个数组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[j]分成两部分看,先算其前半部分a[0]…a[j-1],然后再乘以其后半部分a[j+1]…a[N-1]。具体代码见CPP程序。
两个整数集合A,B,求二者交集、并集、差集
void Intersect(const vector<int>& A,const vector<int>& B,vector<int>& ans)
{
map<int, int> Counter;
const int ASize = A.size(),BSize = B.size();
for(int i=0; i<ASize; ++i)
Counter[A[i]] = 1;
for(int i=0; i<BSize; ++i)
{
if(Counter.count(B[i]))
Counter[B[i]] = 2;
}
map<int, int>::iterator it;
for(it=Counter.begin(); it!=Counter.end(); ++it)
{
if(it->second == 2)
ans.push_back(it->first);
}
}
并集:
void Union(const vector<int>& A,const vector<int>& B,vector<int>& ans)
{
set<int> Exist;
Exist.insert(A.begin(), A.end());
Exist.insert(B.begin(), B.end());
set<int>::iterator it;
for(it=Exist.begin(); it!=Exist.end(); ++it)
ans.push_back(*it);
}
差集:
void Difference(const vector<int>& A,const vector<int>& B,vector<int>& ans)
{
set<int> Unique;
Unique.insert(A.begin(), A.end());
const int BSize = B.size();
for(int i=0; i<BSize; ++i)
Unique.erase(B[i]);//删除在B中也存在的元素
set<int>::iterator it;
for(it=Unique.begin(); it!=Unique.end(); ++it)
ans.push_back(*it);
}
简单测试代码:
int a[] = {1,2,3,4,5,5,4,3,2,1,6,8,10,9,7};
int b[] = {2,2,4,4,8,8,6,6,2,4,6,8};
vector<int> AVec(a,a+sizeof(a)/sizeof(int));
vector<int> BVec(b,b+sizeof(b)/sizeof(int));
vector<int> ans;
cout<<"A: ";
copy(AVec.begin(), AVec.end(), ostream_iterator<int>(cout," "));
cout<<" B: ";
copy(BVec.begin(), BVec.end(), ostream_iterator<int>(cout," "));
Intersect(AVec,BVec,ans);
cout<<" A Intersect B: ";
copy(ans.begin(), ans.end(), ostream_iterator<int>(cout," "));
ans.clear();
Union(AVec,BVec,ans);
cout<<" A Union B: ";
copy(ans.begin(), ans.end(), ostream_iterator<int>(cout," "));
ans.clear();
Difference(AVec,BVec,ans);
cout<<" A - B: ";
copy(ans.begin(), ans.end(), ostream_iterator<int>(cout," "));
举一个例子,
数值: 0,1,2,3,4,5,6,7,8,9
分配: 6,2,1,0,0,0,1,0,0,0
0在下排出现了6次,1在下排出现了2次,
2在下排出现了1次,3在下排出现了0次....
以此类推..
解题思路:关键是理解“要求下排每个数都是先前上排那十个数在下排出现的次数”。
做以下分析:设总共有n个数,上排a[0...n-1],下排b[0...n-1],。
1)下排n个数的累加和为n,即b[0]+b[1]+...+b[n-1] = n
2)ai*bi的累加和也为n,即a[0]*b[0]+a[1]*b[1]+...+a[n-1]*b[n-1] = n
3)对于b中任意一个元素b[j], 都存在i,a[i] = b[j].
4)对于b中任意一个元素b[j],都有b[j] >= 0
5)如果a中存在负数。其在b中出现的次数一定为0. 如果a中数值大于n,则其出现次数也为0.
6)a中至少有两个非0数值在b中出现的次数非0
a:由1)n > n*b[i],其中b[i]为最小值,则a b中一定均有数值0,否则无解。设a[0] = 0,b[0]为a[0]在b中出现次数。
b:由于b中一定存在0,则0的出现次数一定大于0,因此b[0]>0 且b[0] < n,b[1...n-1]中至少一个值为0. 非0元素出现的次数一共是n-b[0].
c:有2)和6)对任意a[i],a[i]*b[i] < n,即b[i] < n/a[i],对所有a[i]>=n/2的元素中,在b中出现的次数必须最多只有1个出现次数不为0,且为1.其余出现次数均为0,即[1, n/2)范围内最多只有n/2-1个元素,故0出现的次数必不小于n/2, [n/2,n)范围内的元素必有一个出现次数为1。因此a数列中也必须有1,否则无解。
d:有c得在数值范围为(0,n/2)中(假设有x这样的数)出现的次数和s为n - b[0]或n-b[0]-1。其中1出现的次数至少为1(由c得)。又如果1出现的次数为1,则1出现的次数已经为2,故1出现的次数必大于1.设为x,则x出现的次数至少为1,而x>1,如果x出现的次数大于1,那么必须要有其他数出现的次数为x,这样无法收敛。故x出现的次数只能为1,1出现的次数只能为2.
另外:(感谢coolria提出)如果上排数列中无0,则下排数列全是0,是其唯一解。
结论:
1)如果上排数列中有0,此时如果上排数列中无0,1,2,n-4这四个数,则下排数列无解;否则下排数列中0出现的次数为n-4;1出现的次数为2;2出现的次数为1;n-4出现的次数为1;其余为0。
2)如果上排数列中无0,则下排数列全0,是其唯一解。
{
int bb = 0;
int aa = 0;
while (bb < lenB && aa < lenA)
{
if (b[bb] < a[aa]) // b小的话,说明不被包含
{
return false;
}
else if (b[bb] > a[aa]) // 如果b大的话,a++
{
aa++;
}
else // 相等的话,都进入下一位
{
bb++;
aa++;
}
}
if (bb == lenB)
{
return true;
}
else
{
return false;
}
return true;
}
问题:
给出一个链表,判断是否有环(可能是首尾相连,也可能是中间的某个节点构成环)。
这个题最开始想的是输入参数包含一个头节点及这个链表的元素个数,那么这样我们在循环的时候加一个步长就可以了,如果steps>len说明肯定存在环了。但是没说给你元素个数怎么办,只给你个头指针。然后我就想开一个数组记录p指针走过的路径,这样每走过一个节点判断这个地址是否走过,这样的话空间复杂度又不行了。看网上的流行解法吧:
步长法:
p=head;
q=head;
while(p && q && q->next)
{
p=p->next;
q=q->next->next;
if(p == q)
return 1;
}
return 0;
解释:p每次走一步,q每次走2步,这样如果存在循环节,我们假设循环节长度为m,那么肯定存在一个整数i使得
(p+i)%m=(q+2*i)%m,这样我们就可以判断是否存在循环节了。这个题可以算是一个拓展思维的好题了。