今天面试面试官提了一个问题:两万个整数、整数有序、平时不会怎么修改,如何使空间最小查找最快。
其实论查找速度当然是常数级别的哈希算法最快了,最简单的哈希就是以数组下标做键,对应数组元素做值。但是哈希可能需要解决冲突,而冲突会带来空间的开销。所以在此提出以数组存储、二分查找查询的办法。二分查找的复杂度是log(n)。
好久没写了,当面竟然没写对,惭愧,回来再好好复习一下。有时候大概懂和能写出来还是有一定距离的。
2、问题是:一个程序有多个线程如何能够知道是哪个线程出现了死循环。一种是运用工具minidown,另外是利用一个守护进程跟踪线程PC是否一直在某个小范围内移动(其实我不知道怎么实现,以后再想)。
3、#include<stdio.h>
#define TOTAL (sizeof(array) / sizeof(array[0]))#define TOTAL_ELEMENTS 7
int array[] = {23,34,12,17,204,99,16};
for(int d=-1;d <= TOTAL_ELEMENTS-2;d++)
这个d会退化为0xfffffff,但是在C++的编译器下这种情况不会发生。
4、如果一个服务器过了两三天突然崩溃了,会是什么原因:
C/C++程序还可能产生另一个指针问题:丢失对已分配内存的引用。当内存是在子程序中被分 配时,通常会出现这种问题,其结果是程序从子程 序中返回时不会释放内存。如此一来,对已分配的内存的引用就会丢失,只要操作系统还在运行中,则进程就会一 直使用该内存。这样的结果 是,曾占用更多的内存的程序会降低系统性能,直到机器完全停止工作,才会完全清空内存。
第二,C指针错误
用C或C++编写的程序,如Web服务器API模块,有可能导致系统的崩溃,因为只要间接引 用指针(即,访问指向的内存)中出现一个错误,就会 导致操作系统终止所有程序。另外,使用了糟糕的C指针的Java模拟量(analog)将访问一个空的 对象引用。Java中的空引用通常不会导致立刻 退出JVM,但是前提是程序员能够使用异常处理方法恰当地处理错误。在这方面,Java无需过多的关注,但 使用Java对可靠性进行额外的度量 则会对性能产生一些负面影响。
第三,数据库中的临时表不够用
许多数据库的临时表(cursor)数目都是固定的,临时表即保留查询结果的内存区域。在临时表中的数据都被读取后,临时表便会被释放,但大量 同时进行的查询可能耗尽数目固定的所有临时表。这时,其他的查询就需要列队等候,直到有临时表被释放时才能再继续运行。
第四,线程死锁
由多线程带来的性能改善是以可靠性为代价的,主要是因为这样有可能产生线程死锁。线程死锁 时,第一个线程等待第二个线程释放资源,而 同时第二个线程又在等待第一个线程释放资源。我们来想像这样一种情形:在人行道上两个人迎面相遇,为了给对方让 道,两人同时向一侧迈出 一步,双方无法通过,又同时向另一侧迈出一步,这样还是无法通过。双方都以同样的迈步方式堵住了对方的去路。假设这种情况一直持续 下 去,这样就不难理解为何会发生死锁现象了。
第五,磁盘已满
导致系统无法正常运行的最可能的原因是磁盘已满。一个好的网络管理员会密切关注磁盘的使用情况,隔一定的时间,就需要将磁盘上的一些负 载转存到备份存储介质中(例如磁带)。日志文件会很快用光所有的磁盘空间。Web服务器的日志文件、SQL*Net的日志文件、 JDBC日志文件, 以及应用程序服务器日志文件均与内存泄漏有同等的危害。可以采取措施将日志文件保存在与操作系统不同的文件系统中。日志文件系统空间已 满时Web服务器也会被挂起,但机器自身被挂起的几率已大大减低。
第六,服务器超载
Netscape Web服务器的每个连接都使用一个线程。Netscape Enterprise Web服务器会在线程用完后挂起,而不为已存在的连接提供任何服 务。如果有一种负载分布机制可以检测到服务器没有响应,则该服务器上的负载就可以分布到其 它的Web服务器上,这可能会致使这些服务器 一个接一个地用光所有的线程。这样一来,整个服务器组都会被挂起。操作系统级别可能还在不断地接收新的连接, 而应用程序(Web服务器) 却无法为这些连接提供服务。用户可以在浏览器状态行上看到connected(已连接)的提示消息,但这以后什么也不会发生。
总之,还有许多因素也极有可能导致Web香港服务器租用或香港服务器托管站点无法工作。有许多种原因可能导致Web站点无法正常工作,这 使得系统地检查所有问题变得很困难。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
|
int
BinSearch(SeqList *R,
int
n,KeyType K)
{
//在有序表R[0..n-1]中进行二分查找,成功时返回结点的位置,失败时返回-1
int
low=0,high=n-1,mid;
//置当前查找区间上、下界的初值
while
(low<=high)
{
if
(R[low].key==K)
return
low;
if
(R[high].key==k)
return
high;
//当前查找区间R[low..high]非空
mid=low+((high-low)/2);
/*使用(low+high)/2会有整数溢出的问题
(问题会出现在当low+high的结果大于表达式结果类型所能表示的最大值时,
这样,产生溢出后再/2是不会产生正确结果的,而low+((high-low)/2)
不存在这个问题*/
if
(R[mid].key==K)
return
mid;
//查找成功返回
if
(R[mid].key<K)
low=mid+1;
//继续在R[mid+1..high]中查找
else
high=mid-1;
//继续在R[low..mid-1]中查找
}
if
(low>high)
return
-1;
//当low>high时表示所查找区间内没有结果,查找失败
}
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
|
int
bsearchWithoutRecursion(
int
array[],
int
low,
int
high,
int
target)
{
while
(low<=high)
{
int
mid=(low+high)/2;
if
(array[mid]>target)
high=mid-1;
else
if
(array[mid]<target)
low=mid+1;
else
return
mid;
}
return
-1;
}
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
|
int
binSearch(
const
int
*Array,
int
start,
int
end,
int
key)
{
int
left,right;
int
mid;
left=start;
right=end;
while
(left<=right)
{
mid=(left+right)/2;
if
(key==Array[mid])
return
mid;
else
if
(key<Array[mid]) right=mid-1;
else
if
(key>Array[mid]) left=mid+1;
}
return
-1;
}
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
|
#include<iostream>
#include<cstdlib>
#include<cstdio>
#include<cmath>
#include<cstring>
#include<algorithm>
using
namespace
std;
int
a[100]={1,2,3,5,12,12,12,15,29,55};
//数组中的数(由小到大)
int
k;
//要找的数字
int
found(
int
x,
int
y)
{
int
m=x+(y-x)/2;
if
(x>y)
//查找完毕没有找到答案,返回-1
return
-1;
else
{
if
(a[m]==k)
return
m;
//找到!返回位置.
else
if
(a[m]>k)
return
found(x,m-1);
//找左边
else
return
found(m+1,y);
//找右边
}
}
int
main()
{
cin>>k;
//输入要找的数字c语言把cin换为scanf即可
cout<<found(0,9);
//从数组a[0]到a[9]c语言把cout换为printf即可
return
0;
}
|