面试--算法题

Posted guangye

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了面试--算法题相关的知识,希望对你有一定的参考价值。

1、红蓝颜料桶问题

【题目】

如果你有两个桶,一个装的是红色的颜料,另一个装的是蓝色的颜料。你从蓝色颜料桶里舀一杯,倒入红色颜料桶,搅拌均匀,再从红色颜料桶里舀一杯倒入蓝颜料桶,也是搅拌均匀。

两个桶中红蓝颜料的比例哪个更高?通过算术的方式来证明这一点。

【答案】

蓝桶的 蓝红比例  和 红桶的  红蓝比例,是一样的。

【计算过程】

假设桶的容量大小为L,一勺子的容量大小为X

 

第一步操作: 

蓝桶:L-X

红桶: L+X

备注:红桶中,混合均匀,所以红蓝颜料的比例:L:X

 

第二步操作:

红桶:红蓝颜料的比例不变,因为是均匀的。比例还是L:X

蓝桶: 

蓝色:L-X +   (X/(L+X))*X  = ((L-X)*(L+X)+X*X)/(L+X)

红色: (L/(L+X))*X=(XL)/(L+X)

所以 蓝红 比例,底都乘以 (L+X):

蓝:L*L-X*X +X*X = L*L

红:L*X

所以 蓝桶的蓝红比例是:L:X  和红桶的红蓝比例是一样的

【注意】:(x+y)(x-y) 平方差 =x²-y²

 

2、一个类,实现一个数组的循环队列,写出入队列、出队列、是否为空和获取长度的方法

 1 class loopArray
 2 {
 3   private $size = 100;
 4   private $arr = [];
 5 
 6   public function __construct(int $size)
 7   {
 8     if ($size  > 1) {
 9       $this->size = $size;
10     }
11   }
12 
13   //入队列
14   public function push(string $data)
15   {
16     if (count($this->arr) == $this->size) {
17       return false;
18     } else {
19       $this->arr[] = $data;
20       return true;
21     }
22   }
23 
24   // 出队列
25   public function pull()
26   {
27     if (empty($this->arr)) {
28       return false;
29     } else {
30         return array_shift($this->arr);
31     }
32   }
33 
34   // 是否为空  true:为空  false:不为空
35   public function isEmpty()
36   {
37     return empty($this->arr); 
38   }
39 
40   // 获取长度
41   public function getSize()
42   {
43     return count($this->arr);
44   }
45 }

 

3、RGB字母排序问题

RGB排序,一个字符串,里面只有三种字符R G B,所有的R都在G的前面,所有的G都在B的前面。

将给定字符串按照此规律排序。要求不允许用辅助空间(如果要使用辅助空间,不能是整个数组那么长的空间复制一遍),复杂度控制在O(N)。

 【难度分析】本道题难在如何控制时间复杂度和空间复杂度, 空间负责度的话,就是不能传值,传地址会减少空间的复制。

因为这种题目的局限性,3个字母,而且是RGB降序,所以冒泡算法是个不错的算法。但是如果不用冒泡算法,怎么处理?下面给出答案。

 

参考:

https://blog.csdn.net/weixin_44124500/article/details/85039699

https://blog.csdn.net/brucehb/article/details/12363085

感觉上面2篇文章的算法可能有点问题,感觉啦,也可能我自己没看懂,下面是我自己的算法,测试过是没问题的

 1 <?php
 2 
 3 function deal(array &$arr)
 4 {
 5         $len = count($arr);
 6         $i = -1;
 7         while ($i<$len && $arr[$i+1] == ‘R‘){
 8                 $i++;
 9         }
10         $j = $len;
11         while ($j>0 && $arr[$j-1] == ‘B‘){
12                 $j--;
13         }
14 
15         $p = $i+1;
16         while ($p < $j) {
17                 if ($arr[$p] == ‘R‘) {
18                         $i++;
19                         // 交换值
20                         if ($arr[$i] != $arr[$p]) {
21                                 $temp = $arr[$i];
22                                 $arr[$i] = $arr[$p];
23                                 $arr[$p] = $temp;
24                         } else {
25                                 $p++;
26                         }
27                 } else if ($arr[$p] == ‘B‘) {
28                         $j--;
29                         // 交换值
30                         if ($arr[$j] != $arr[$p]) {
31                                 $temp = $arr[$j];
32                                 $arr[$j] = $arr[$p];
33                                 $arr[$p] = $temp;
34                         } 
35                 } else {
36                         $p++;
37                 }
38         }
39 }
40 
41 $arr = ‘GBBRRGGBBRBGRBGBBRRGGGGBGGGGRRRRBBGGRRR‘;
42 $arr = str_split($arr);
43 //print_r($arr);
44 deal($arr);
45 //print_r($arr);
46 print_r(implode(‘‘,$arr));
47 echo PHP_EOL;

输出结果:RRRRRRRRRRRRRGGGGGGGGGGGGGGGBBBBBBBBBBB

【思路】

设置3个“指针”,i和j、p,对php的数组来说,就是对应的数组下标。

i是指向-1,如果左起第一个字符是R,那么往后找第一个非R处停止。

举例,如果字符串是“RRRGB。。。”那么i的初始值是2,p的初始值是3

如果字符串“GBR。。。。”,非R字母开头的,那么i的初始值是-1,p的初始值是0

同理来设置j的初始值,要么是n,要么是右起第一个非B的字符

举例,如果字符串“。。。。GBBB”, 假设字符串长度100,那么j的初始值就是97

如果字符串“。。。。G”,非B字符结尾,那么j的初始值就是100。

 

p是i的下一位,p本身的值不可能是R,因为p是i+1, i+1非R字符

往下就是如果$p对应的数组元素值是 G 则p++,指向下一个数组元素

如果是$arr[$p] == ‘B‘则跟$j--的元素交换,如果$j--的元素值和$p对应的数组元素值相同,则继续$j--,直到$arr[$j]跟 $arr[$p]不同,前提是$p < $j

如果是$arr[$p] == ‘R‘,则跟$i ++ 后的数组元素值交换,如果$arr[$i] == $arr[$p] 则不交换,$p++

 

 4、斐波那契数列的优化算法

斐波那契数列:1、1、2、3、5、8、13、21。。。规律就是从第三个数开始的每一个数等于前面2个数之和。

 一般来说,递归的算法:

1 <?php
2 function fibonacci(int $n) {
3   if($n <= 2) {
4        return 1;
5   }
6   return fibonacci($n-2) + fibonacci($n-1);
7 }

上面的算法,用到了2层递归,所以效率上并不是最优的,有没有更优的办法?

【思路】用空间换时间,参考:https://blog.csdn.net/u010183728/article/details/81238401

 1 <?php
 2 function fibonacci(int $n) {
 3   if($n <= 2) {
 4        return 1;
 5   }
 6   $f = 0;
 7   $g = 1;
 8   $result = 0;
 9   for($i = 1; $i < $n; $i++) {
10     $result = $f + $g;
11     $f = $g;
12     $g = $result;
13   }
14   return $result;
15 }

以$n = 3来解析下上面的算法的执行过程:

1)当$i=1时, $result = 0+1 = 1 ; $f = 1; $g=1;

2)  当$i=2时,$result = 1+1 = 2;

3)  当$i=3时,for循环没有执行,所以,最终$result的值就是2

 【总结】空间换时间,$f 和 $g保存 前面的2个数的值, $result = 前面2个数之和。

 

 

以上是关于面试--算法题的主要内容,如果未能解决你的问题,请参考以下文章

算法面试手撕代码高频题汇集

算法刷题范围建议 和 代码规范

算法刷题范围建议 和 代码规范

高频算法面试题_旋转字符串(完整的代码实现)

Java进阶之光!2021必看-Java高级面试题总结

深度学习/机器视觉/数字IC/FPGA/算法手撕代码目录总汇