一、给一个数 N,判定这个数是否是素数。
1、先让面试者说素数的定义,如果不知道可以提示素数的定义
2、最差的面试者,会没有思路,这是很可怕的,大学第一学期学完,应该学会这个题
3、一般的面试者,能比较费劲地写出正确的程序,但是可能存在边界、标记等问题。
4、写出程序出来,可以进一步问,优化的空间,在哪里,所谓优化,无非就是时间和空间复杂度。
5、只有少数的面试者,能进行几轮优化
6、有训练的面试者可能知道一些特定的高效方法
check_ss(8);
function check_ss($num) {
for($i=2; $i < $num ; $i++) {
if($num % $i == 0) {
echo $num. '不是素数';
exit;
}
}
echo $num. '是素数';
}
二、给一个数 N,把 2 到 N 之间的素数输出出来
1、这个题比上面这个难度加大了一层
2、可以限定,不让其使用子函数,增加逻辑上的复杂度
3、其他的,同样一层层考优化的方法
$no=0;//用于标记经检验前后是否是素数,0表示是;1不是;
for($i=2;$i<=1000;$i++){//循环2-1000
for($j=2;$j
if($i%$j==0){
$no=1;//如果取余得0,不是素数,改值为1
}
}
if($no==0){echo $i;}//经过检验后如果$no仍为0,则$i是素数。
}
?>
三、写出三角状的 9*9 乘法表
1、这个题目面向基础比较差的面试者
2、最差的面试者,也会说没有思路,在学校会写,现在忘记了
3、比较一般的能写出来,更进行一步的,可以让其用几种循环来写,写倒三角
4、如果都没有问题,循环思维逻辑值得肯定
for($a = 1; $a <10; $a++){
echo "
echo "
";for ($b=1; $b <= $a; $b++) {
echo "
";echo "$a*$b=".$a*$b;
echo "
";}
echo "
";echo "
";}
?>
四、用递归编写求和或者求阶乘的函数
1、可以先让其不用递归写一遍
2、再让其递归实现
3、最差的面试者同样无法下手
4、接下来可以探讨递归的一些优劣之处,在哪些常见算法中用到了递归
5、也可以问问1024的阶乘有多少个零这种的问题。
php递归的方法求和1+2+3+...+n
function add($n){
if($n==1) return 1;
else
return $n+add($n-1); //没注意
}
用php实现1+(1+2)+(1+2+3)+...+(1+2+...n) 递归求和
function getSum($n) {
if ($n > 1) {
$tempSum = $n * (1 + $n) / 2; // 当然这部分可以拆成另一个递归来求和,如果有需要在说
return $tempSum + getSum(--$n);
}
else {
return $n;
}
}
$result = getSum(20);
求n的阶乘
function f($n)
{
$out = -1;
if($n<0)
echo "输入不能是负数";
else if($n==0||$n==1)
$out=1;
else $out=f($n-1)*$n;
return $out;
}
echo f(6);
?>
五、将字符串反转,比如 “abcdefg” 转化为 "gfedcba"
1、如果面试者使用 C 语言效果最佳
2、可以进一步考察这种形式的反转算法, www.ucai.cn => cn.ucai.www
$str = "hello";
function fan($str) {
//声明一个临时的变量
$n = "";
//获取字符串长度
$m = strlen($str)-1;
for($i=$m; $i >= 0; $i--) {
$n .= $str{$i};
}
return $n;
}
echo fan($str);
?>
支持中文:
function getRev($str,$encoding='utf-8'){
$result = '';
$len = mb_strlen($str);
for($i=$len-1; $i>=0; $i--){
$result .= mb_substr($str,$i,1,$encoding);
}
return $result;
}
$string = 'OK你是正确的Ole';
echo getRev($string);
?>
六、求出 IPV4 IP地址所对应的整数,比如 192.168.199.1 对应整数 3232286465
1、可以先让其求字符串所对应的整数这个简单算法
2、如果面试者使用 C 语言效果最佳
$ip = gethostbyname('www.sharejs.com');
$out = "The following URLs are equivalent:
\n";
$out .= 'http://www.sharejs.com/, http://' . $ip . '/, and http://' . sprintf("%u",
ip2long($ip)) . "/
\n";
echo $out;
?>
这是如何计算的,目前我知道有两个算法。
其一
function ip2int($ip){
//我们先把ip分为四段,$ip1,$ip2,$ip3,$ip4
list($ip1,$ip2,$ip3,$ip4)=explode(".",$ip);
//然后第一段乘以256的三次方,第二段乘以256的平方,第三段乘以256
//这即是我们得到的值
return $ip1*pow(256,3)+$ip2*pow(256,2)+$ip3*256+$ip4;
}
?>
其二,用位运算
function ip2int($ip){
list($ip1,$ip2,$ip3,$ip4)=explode(".",$ip);
return ($ip1<<24)|($ip2<<16)|($ip3<<8)|($ip4);
}
?>
我们会发现,有些ip转化成整数后,是负的,这是因为得到的结果是有符号整型,最大值是2147483647.
要把它转化为无符号的,可以用
sprintf("%u",ip2long($ip);
就能转换为正整数。而且得到的结果用long2ip也可以正常转换回原来的ip地址。也可以用ip2long来验
证一个ip是否是有效的,如
function chk_ip($ip){
if(ip2long($ip)=="-1") {
return false;
}
return true;
}
//应用
var_export(chk_ip("10.111.149.42"));
var_export(chk_ip("10.111.256.42"));
?>
将输出true和false
七、使用最高效的算法,将一堆100以内的数排序,不能使用排序的库函数
1、不允许使用现成的各种排序算法
2、要求一遍遍历完成即实现排序
3、也可以问:如何对n个数进行排序,要求时间复杂度O(n),空间复杂度O(1)
看上去似乎任何已知的算法都无法做到,如果谁做到了,那么所有的排序方法:QuickSort,ShellSort
,HeapSort,BubbleSort等等等等,都可以扔掉了,还要这些算法干吗阿,呵呵。不过实际上,在数字
范围有限制的情况下,是有一个这样的算法的,只需要用一个数组记录每个数字出现次数就可以了。
假定你的数字范围在0到65535范围之内,定义一个数组count[65536](这个空间是常量,和n无关,所以
是O(1) ),初值全部为0。
那么假设有下面这些数字:
100
200
300
119
0
6
...
那么对于每个这个数字,都做在count中记录一下:
100 => count[100]++
200 => count[200]++
300 => count[300]++
119 => count[119]++
0 => count[0]++
6 => count[6]++
...
最后,遍历一边所有这些数字就可得到0~65535每个数字的个数(在count数组中),然后再顺序遍历
count数组,count[n] = m,则输出m个n,(比如说有count[3] = 2, 那么说明有2个数字3),依次输出
,最后可得结果。第一次遍历是O(n),第二次遍历是O(1),为常量,所以最后的时间复杂度为O(n),而
空间复杂度为O(1)
#include
int main()
{
int a[] = {10,6,9,5,2,8,4,7,1,3};
int len = sizeof(a) / sizeof(int);
int temp;
for(int i = 0; i < len; )
{
temp = a[a[i] – 1];
a[a[i] – 1] = a[i];
a[i] = temp;
if ( a[i] == i + 1)
i++;
}
for (int j = 0; j < len; j++)
cout< return 0;
}
这个算法很简单,相信大家都会,只是这个题太过于变态了,一般会把面试者吓住
八、有上千万个1000万以内的数据,请排除掉重复的数
1、可以转化为找出重复的数
2、要求空间最省
3、要求一次遍历完成整个查找
4、延伸:如果用 Shell 命令实现怎么办?通过awk去除重复行
100万条,也就是16M而已,内存顶得住的。
遍历一遍,在内存里构造一个该数据的hash表,就搞定了。
参考:
1、怎么在海量数据中找出重复次数最多的一个?
方案1:先做hash,然后求模映射为小文件,求出每个小文件中重复次数最多的一个,并记录重复
次数。然后找出上一步求出的数据中重复次数最多的一个就是所求(具体参考前面的题)。
2、上千万或上亿数据(有重复),统计其中出现次数最多的钱N个数据。
方案1:上千万或上亿的数据,现在的机器的内存应该能存下。所以考虑采用hash_map/搜索二叉树/
红黑树等来进行统计次数。然后就是取出前N个出现次数最多的数据了,可以用第2题提到的堆机制完成
。
九、如果从1000万行左右的文件中,随机地取出 10万行左右的样本数据
1、要求一遍文件扫描完成数据获取
2、空间最省,将结果输出在另外一个文件中
3、可以要求写出完整程序,包括 fopen 的使用等
十、字符串库函数的相关实现思路
1、检测一个字符串是否包含在另一个字符串中
2、实现 trim 函数、strlen 函数
3、复杂一些的:求出给定字符串中最长的回文字符的长度以及把它们给输出来。
strpos($a, $b) !== false 如果$a 中存在 $b,则为 true ,否则为 false。
用 !== false (或者 === false) 的原因是如果 $b 正好位于$a的开始部分,那么该函数会返回int
(0),那么0是false,但$b确实位于$a中,所以要用 !== 判断一下类型,要确保是严格的 false。
其它的还有 PHP 原生支持的函数,如 strstr(),stristr() 等,直接判断就可以了。
通过正则表达式替换,功能更强
php去除字符串首尾空格(包括全角)
复制代码 代码如下:
$str=" ";
$str = mb_ereg_replace('^( | )+', '', $str);
$str = mb_ereg_replace('( | )+$', '', $str);
echo mb_ereg_replace(' ', "\n ", $str);
?>
计字串长度: while ( isset($str{$i}) && ++$i );