1、封禁策略為一個自然分鐘內請求籤到介面500次則封禁該IP10分鐘,如何操作?
<?php
//設定兩個redis key來支撐此問題
function getUserState($ip = ``){
if (empty($ip)) {
return true;
}
//獲取封禁key
$bannedKey = `redis_cache_` . $ip;
if ($redis->get($bannedKey)) {
return true;
}
//獲取次數key
$ipNumKey = `redis_cache_num_`. $ip
$ipNum = $redis->incr($ipNumKey);
if ($ipNum >= 500) {
$redis->setex($bannedKey,600);
return false;
}
return true;
}
?>
2、只提供10M記憶體,現在要做一個活動,參與活動的使用者userId為1~10000000,請問如何設計?
可考慮用redis的setbit和getbit命令來實現此需求,對其userId進行佔位,並且8各userId的佔位才佔有1B的空間,所有10M空間足足有餘
3、下面程式碼的輸出值為?
<?php
$nums = [1,2,3];
foreach ($nums as &$num) {
//null
}
echo $nums[0].`-`.$num[1].`-`.$nums[2];//1-2-3
foreach ($nums as $num) {
//null
}
echo $nums[0].`-`.$num[1].`-`.$nums[2];//1-2-2
?>
如果不明白,則有直達地址:PHP引用那些事兒
4、實現一個base62_encode()和base62_decode()方法,要求base62_encode(1)=1,base62_encode(61)=z,base62_decode(`z`)=61;語言不限
<?php
//如果有經驗的RD,一眼就知道62個字元是0-9A-Za-z,並且在微博推出的短鏈服務就知道,這是一道通向短鏈設計的一個必經之路,具體短鏈服務不懂怎麼設計的自行google,這裡不做過多解釋
class Base62
{
private $string = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
public function base62_encode($str)
{
$out = ``;
for ($t = floor(log10($str) / log10(62)); $t >= 0; $t--) {
$a = floor($str / pow(62, $t));
$out = $out . substr($this->string, $a, 1);
$str = $str - ($a * pow(62, $t));
}
return $out;
}
public function base62_decode($str)
{
$out = 0;
$len = strlen($str) - 1;
for ($t = 0; $t <= $len; $t++) {
$out = $out + strpos($this->string, substr($str, $t, 1)) * pow(62, $len - $t);
}
return substr(sprintf("%f", $out) , 0, -7);
}
}
$object = new Base62();
echo $object->base62_encode(1) . "<br/>";
echo $object->base62_encode(61) . "<br/>";
echo $object->base62_decode(`z`) . "<br/>";
?>
5、PHP實現KMP演算法
如果只知道PHP是拍簧片技術,而不懂看毛片演算法,就low爆了,KMP演算法講解
<?php
function KMP($str)
{
$K = [0];
$M = 0;
for ($i = 1; $i < strlen($str); $i++) {
if ($str[$i] == $str[$M]) {
$K[$i] = $K[$i - 1] + 1;
$M++;
} else {
$M = 0;
$K[$i] = $K[$M];
}
}
return $K;
}
// KMP查詢
function KMPMatch($src, $par, $debug = false)
{
$K = KMP($par);
for ($i = 0, $j = 0; $i < strlen($src);) {
if ($j == strlen($par)) return $i - $j;
echo $i, " ", $j, " ", $src[$i], $par[$j], "<BR>";
if ($par[$j] === $src[$i]) {
$j++;
$i++;
} else {
if ($j === 0 && $par[$j] != $src[$i]) {
$i++;
}
$j = $K[$j - 1 >= 0 ? $j - 1 : 0];
}
}
return false;
}
//測試資料
$src = `BBC ABCDAB ABCDABCDABDE`;
$par = `ABCDABD`;
// 匹配值
echo "匹配值:", implode(" ", KMP($par)), "<BR>";
// 在給定的字串中查詢特定字元(串)
echo KMPMatch($src, $par, true), "<BR>";
6、實現中英文字串翻轉的操作
<?php
function mb_strrev($str)
{
//判斷輸入的是不是utf8型別的字元,否則退出
if (!is_string($str) || !mb_check_encoding($str, `UTF-8`)) {
exit("輸入型別不是UTF8型別的字串");
}
$array = array();
//將字串存入陣列
$l = mb_strlen($str, `UTF-8`);
for ($i = 0; $i < $l; $i++) {
$array[] = mb_substr($str, $i, 1, `UTF-8`);
}
//反轉字串
krsort($array);
//拼接字串
$string = implode($array);
return $string;
}
$str1 = "我是一箇中國人Chinese";
echo $str1 . "->" . mb_strrev($str1) . "<br>";
7、PHP實現相關查詢演算法
<?php
/**
* 二分查詢演算法
* 初始陣列為排好序的
* binary()非遞迴
* binaryRecursive() 遞迴
**/
$arr = [1, 3, 9, 23, 54];
function binary($arr, $low, $top, $target)
{
while ($low <= $top) {
$mid = floor(($low + $top) / 2);
if ($arr[$mid] == $target) {
return $mid;
} elseif ($arr[$mid] < $target) {
$low = $mid + 1;
} else {
$top = $mid - 1;
}
}
return -1;
}
function binaryRecursive($arr, $low, $top, $target)
{
if ($low <= $top) {
$mid = floor(($low + $top) / 2);
if ($arr[$mid] == $target) {
return $mid;
} elseif ($arr[$mid] < $target) {
return binaryRecursive($arr, $mid + 1, $top, $target);
} else {
return binaryRecursive($arr, $low, $mid - 1, $target);
}
} else {
return -1;
}
}
echo binary($arr, 0, count($arr) , 9);//2
echo binaryRecursive($arr, 0, count($arr) , 9);//2
/**
* 順序查詢
**/
$arr = [1, 2, 3, 4];
function query_search($val)
{
global $arr;
foreach ($arr as $k => $v) {
if ($v == $val) {
echo `順序查詢成功,KEY=>` . $k;
exit(0);
}
}
echo `順序查詢失敗!`;
}
echo query_search(3);
//順序查詢成功,KEY=>2
/**
* 插入查詢
* 陣列資料需要有序
**/
$i = 0;
function insertsearch($arr, $num)
{
$count = count($arr);
$lower = 0;
$high = $count - 1;
global $i;
while ($lower <= $high) {
$i++; //計數器
if ($arr[$lower] == $num) {
return $lower;
}
if ($arr[$high] == $num) {
return $high;
}
$middle = intval($lower + ($num - $arr[$lower]) / ($arr[$high] - $arr[$lower]) * ($high - $lower));
if ($num < $arr[$middle]) {
$high = $middle - 1;
} else if ($num > $arr[$middle]) {
$lower = $middle + 1;
} else {
return $middle;
}
}
return -1;
}
$arr = [0, 1, 16, 24, 35, 47, 59, 62, 73, 88, 99];
$pos = insertsearch($arr, 62);
echo $pos;//7
echo $i;//2 如果是折半查詢的話i=3;
8、PHP實現相關排序演算法
<?php
/**
* 快速排序演算法
**/
$arr = [6, 3, 8, 6, 4, 2, 9, 5, 1];
//函式實現快速排序
function quick_sort($arr)
{
if (!is_array($arr)) {
return false;
}
$length = count($arr);
if ($length <= 1) {
return $arr;
}
$left = $right = [];
for ($i = 1; $i < $length; $i++) {
//判斷當前元素的大小
if ($arr[$i] < $arr[0]) {
$left[] = $arr[$i];
} else {
$right[] = $arr[$i];
}
}
//遞迴呼叫
$left = quick_sort($left);
$left[] = $arr[0];
$right = quick_sort($right);
//將所有的結果合併
return array_merge($left, $right);
}
print_r(quick_sort($arr));
//Array ( [0] => 1 [1] => 2 [2] => 3 [3] => 4 [4] => 5 [5] => 6 [6] => 6 [7] => 8 [8] => 9 )
9、PHP實現數獨求解問題
<?php
/**
* 規則每行每列每宮的數字都是1-9個數字組成,不能重複
**/
class ShuDu
{
public $matrix;
public function __construct($arr = null)
{
if ($arr == null) {
$this->clear();
} else {
$this->matrix = $arr;
}
}
public function clear()
{
for ($i = 0; $i < 9; $i++) {
for ($j = 0; $j < 9; $j++) {
$this->matrix[$i][$j] = [];
for ($k = 1; $k <= 9; $k++) {
$this->matrix[$i][$j][$k] = $k;
}
}
}
}
public function setCell($row, $col, $value)
{
$this->matrix[$row][$col] = [$value => $value];
//row
for ($i = 0; $i < 9; $i++) {
if ($i != $col) {
if (!$this->removeValue($row, $i, $value)) {
return false;
}
}
}
//col
for ($i = 0; $i < 9; $i++) {
if ($i != $row) {
if (!$this->removeValue($i, $col, $value)) {
return false;
}
}
}
//square
$rs = intval($row / 3) * 3;
$cs = intval($col / 3) * 3;
for ($i = $rs; $i < $rs + 3; $i++) {
for ($j = $cs; $j < $cs + 3; $j++) {
if ($i != $row && $j != $col) {
if (!$this->removeValue($i, $j, $value)) return false;
}
}
}
return true;
}
public function removeValue($row, $col, $value)
{
$count = count($this->matrix[$row][$col]);
if ($count == 1) {
$ret = !isset($this->matrix[$row][$col][$value]);
return $ret;
}
if (isset($this->matrix[$row][$col][$value])) {
unset($this->matrix[$row][$col][$value]);
if ($count - 1 == 1) {
return $this->setCell($row, $col, current($this->matrix[$row][$col]));
}
}
return true;
}
public function set($arr)
{
for ($i = 0; $i < 9; $i++) {
for ($j = 0; $j < 9; $j++) {
if ($arr[$i][$j] > 0) {
$this->setCell($i, $j, $arr[$i][$j]);
}
}
}
}
public function dump()
{
for ($i = 0; $i < 9; $i++) {
for ($j = 0; $j < 9; $j++) {
$c = count($this->matrix[$i][$j]);
if ($c == 1) {
echo " " . current($this->matrix[$i][$j]) . " ";
} else {
echo "(" . $c . ")";
}
}
echo "<br/>";
}
echo "<br/>";
}
public function dumpAll()
{
for ($i = 0; $i < 9; $i++) {
for ($j = 0; $j < 9; $j++) {
echo implode(``, $this->matrix[$i][$j]) , " ";
}
echo "<br/>";
}
echo "<br/>";
}
public function calc($data)
{
$this->clear();
$this->set($data);
$this->_calc();
$this->dump();
}
public function _calc()
{
for ($i = 0; $i < 9; $i++) {
for ($j = 0; $j < 9; $j++) {
if (count($this->matrix[$i][$j]) == 1) {
continue;
}
foreach ($this->matrix[$i][$j] as $v) {
$flag = false;
$t = new Sudoku($this->matrix);
if (!$t->setCell($i, $j, $v)) {
continue;
}
if (!$t->_calc()) {
continue;
}
$this->matrix = $t->matrix;
return true;
}
return false;
}
}
return true;
}
}
$sd = new ShuDu();
$sd->calc([
[0, 5, 0, 0, 0, 6, 0, 9, 0],
[0, 4, 7, 0, 8, 2, 6, 0, 0],
[0, 8, 0, 0, 0, 7, 0, 5, 2],
[7, 0, 1, 0, 3, 4, 0, 0, 6],
[0, 3, 0, 0, 2, 0, 0, 8, 0],
[2, 0, 0, 0, 0, 1, 9, 0, 4],
[4, 7, 0, 1, 0, 0, 0, 6, 0],
[0, 0, 9, 4, 6, 0, 3, 7, 0],
[0, 1, 0, 2, 0, 0, 0, 4, 0],
]);
10、PHP中的Trait特性
PHP是單繼承的語言,在PHP 5.4 Traits出現之前,PHP的類無法同時從兩個基類繼承屬性或方法。php的Traits和Go語言的組合功能類似,通過在類中使用use關鍵字宣告要組合的Trait名稱,而具體某個Trait的宣告使用trait關鍵詞,Trait不能直接例項化,下面有篇文章比較詳細的介紹了此功能,PHP-Trait特性詳解
11、深刻理解PHP中的淺複製和深複製
<?php
/**
* 深複製的原理是A的改變不會影響B的改變
* 淺複製的原理是A的改變會影響B的改變
**/
class ObjA
{
public $num = 0;
public $objB; //包含的物件
function __construct()
{
$this->objB = new ObjB();
}
//只有實現了下面方法聚合類 才能實現深複製
/*function __clone() {
$this->objB = clone $this->objB;
}*/
}
class ObjB
{
public $num2 = 0;
}
//原型物件
$objA = new ObjA();
//複製物件(=複製引用)
$objA2 = $objA;
$objA2->num = 2;
//隨著$objA2->num的變化 $objA->num也變化了
print_r($objA->num . `<br/>`); //結果為2
print_r($objA2->num . `<br/>`); //結果為2
//複製物件(‘clone’關鍵字克隆)
$objA3 = clone $objA;
$objA3->num = 4;
//隨著$objA3->num的變化 $objA->num沒有變化
print_r($objA->num . `<br/>`); //結果為2
print_r($objA3->num . `<br/>`); //結果為4
//但是clone的物件(是聚合類)中包含其他物件時所包含的物件(objB)複製的是引用
$objA3->objB->num2 = 7;
print_r($objA3->objB->num2 . `<br/>`); //結果是7
print_r($objA->objB->num2 . `<br/>`); //結果是7