https://leetcode.com/problems/longest-common-prefix/submissions/

Approach 1: Horizontal scanning

Leetcode#14. Longest Common Prefix_php

* Solution.php

<?php

class Solution {

    /**
     * @param $haystack string
     * @param $needle string
     * @return int
     */
    private static function indexOf($haystack, $needle) {
        $j = 0;
        $m = strlen($haystack);
        $n = strlen($needle);
        for ($i = 0; $i < $m && $j < $n; $i++) {
            if ($needle[$j] === $haystack[$i]) {
                $j += 1;
            } else {
                $j = 0;
            }
        }
        if ($i >= $m && $j < $n) {
            return -1;
        }
        return $i - $j;
    }

    /**
     * @param $s string
     * @param $start int
     * @param $end int
     * @return bool|string
     */
    private static function substring($s, $start, $end) {
//        $t = "";
//        for ($i = $start; $i < $end; $i++) {
//            $t .= $s[$i];
//        }
//        return $t;
        return substr($s, $start, $end - $start);
    }

    /**
     * @param String[] $strs
     * @return String
     */
    public function longestCommonPrefix($strs) {
        if (!isset($strs[0])) {
            return "";
        }
        // 假设公共前缀就是数组第0个元素
        $prefix = $strs[0];
        $le = count($strs);
        // 遍历第1个到最后1个
        for ($i = 1; $i < $le; $i++) {
            // 测试公共前缀
            while (self::indexOf($strs[$i], $prefix) !== 0) {
                // 前缀超长 缩短1位再试
                $prefix = self::substring($prefix, 0, strlen($prefix)-1);
                if (empty($prefix)) {
                    return "";
                }
            }
        }
        return $prefix;
    }
}

Test cases:

* index.php

<?php

include "Solution.php";

$sln = new Solution();
$a = ["flower","flow","flight"];
printf("%s\n", $sln->longestCommonPrefix($a));

$a = ["leets","leetcode","leet", "leeds"];
printf("%s\n", $sln->longestCommonPrefix($a));

$a = ["aa","a"];
printf("%s\n", $sln->longestCommonPrefix($a));

$a = ["dog","racecar","car"];
printf("%s\n", $sln->longestCommonPrefix($a));

fl
lee
a

Approach 2: Vertical scanning
* Solution.php

<?php

class Solution {

    /**
     * @param $s string
     * @param $start int
     * @param $end int
     * @return bool|string
     */
    private static function substring($s, $start, $end) {
        return substr($s, $start, $end - $start);
    }

    /**
     * @param String[] $strs
     * @return String
     */
    public function longestCommonPrefix($strs) {
        $n = count($strs);
        if (is_null($strs) || $n === 0) {
            return "";
        }
        $le = strlen($strs[0]);
        for ($i = 0; $i < $le; $i++) {
            $c = $strs[0][$i];
            for ($j = 1; $j < $n; $j++) {
                if ($i === strlen($strs[$j]) || $strs[$j][$i] !== $c) {
                    return self::substring($strs[0], 0, $i);
                }
            }
        }
        return $strs[0];
    }
}

 

Approach 3: Divide and conquer

* Solution.php

<?php

class Solution {

    /**
     * @param $s string
     * @param $start int
     * @param $end int
     * @return bool|string
     */
    private static function substring($s, $start, $end) {
        return substr($s, $start, $end - $start);
    }

    /**
     * @param $left string
     * @param $right string
     * @return string
     */
    private static function commonPrefix($left, $right) {
        $m = strlen($left);
        $n = strlen($right);
        $min = $m < $n ? $m : $n;
        for ($i = 0; $i < $min; $i++) {
            if ($left[$i] != $right[$i]) {
                return self::substring($left,0, $i);
            }
        }
        return self::substring($left, 0, $min);
    }

    /**
     * @param $strs String[]
     * @param $l int
     * @param $r int
     * @return string
     */
    private static function lcp($strs, $l, $r) {
        if ($l >= $r) {
            return $strs[$l];
        }
        $mid = floor($l + $r) / 2;
        $lcpLeft = self::lcp($strs, $l, $mid);
        $lcpRight = self::lcp($strs, $mid+1, $r);
        return self::commonPrefix($lcpLeft, $lcpRight);
    }

    /**
     * @param String[] $strs
     * @return String
     */
    public function longestCommonPrefix($strs) {
        $n = count($strs);
        if (is_null($strs) || $n===0) {
            return "";
        }
        return self::lcp($strs, 0, $n-1);
    }
}

Leetcode#14. Longest Common Prefix_leetcode_02

 

Approach 4: Binary search

Leetcode#14. Longest Common Prefix_ide_03

class Solution {

    /**
     * @param $s string
     * @param $start int
     * @param $end int
     * @return bool|string
     */
    private static function substring($s, $start, $end) {
        return substr($s, $start, $end - $start);
    }

    /**
     * @param $s string
     * @param $t string
     * @return bool
     */
    private static function startsWith($s, $t) {
        for ($i = 0; isset($t[$i]); $i++) {
            if ($s[$i] !== $t[$i]) {
                return false;
            }
        }
        return true;
    }

    /**
     * @param $strs String[]
     * @param $len int
     * @return bool
     */
    private static function isCommonPrefix($strs, $len) {
        $str1 = self::substring($strs[0], 0, $len);
        $n = count($strs);
        for ($i = 1; $i < $n; $i++) {
            if (!self::startsWith($strs[$i], $str1)) {
                return false;
            }
        }
        return true;
    }


    /**
     * @param String[] $strs
     * @return String
     */
    public function longestCommonPrefix($strs) {
        $n = count($strs);
        if (is_null($strs) || $n===0) {
            return "";
        }
        $minLen = 2147483647;
        foreach ($strs as $str) {
            $minLen = min($minLen, strlen($str));
        }
        $low = 0;
        $high = $minLen;
        while ($low <= $high) {
            $middle = floor(($low + $high) / 2);
            if (self::isCommonPrefix($strs, $middle)) {
                $low = $middle + 1;
            } else {
                $high = $middle - 1;
            }
        }
        return self::substring($strs[0], 0, floor(($low + $high)/2));
    }
}