Longest Common Prefix

Problem

Write a function to find the longest common prefix string amongst an array of strings.

Related Topics:

String

Analysis

水平扫描

垂直扫描

以列为单位扫描,适用于存在短字符串的情况。

分治

将字符串划分为多组,每组各自比较后,再合并比较。

长度二分

以最短的字符串长度为基础,将长度进行二分,然后将第一个元素,按长度切割后比较。

前缀树

建立前缀树,进行查询。

Code

水平扫描

class Solution {

    fun longestCommonPrefix(strs: Array<String>): String {

        if (strs.isEmpty()) {
            return ""
        }

        val prefix = strs[0]
        var len = prefix.length

        for (i in 1 until strs.size) {
            while (!strs[i].regionMatches(0, prefix, 0, len)) {
                len--
            }
        }

        return prefix.substring(0, len)
    }
}

垂直扫描

class Solution {

    fun longestCommonPrefix(strs: Array<String>): String {

        if (strs.isEmpty()) {
            return ""
        }

        for (i in 0 until strs[0].length) {
            (1 until strs.size)
                    .firstOrNull { i == strs[it].length || strs[0][i] != strs[it][i] }
                    ?.let { return strs[0].substring(0, i) }
        }

        return strs[0]
    }
}

分治

class Solution {

    fun longestCommonPrefix(strs: Array<String>): String {

        if (strs.isEmpty()) {
            return ""
        }

        return divideAndConquer(strs, 0, strs.size - 1)
    }

    private fun divideAndConquer(strs: Array<String>, left: Int, right: Int): String {

        if (left == right) {
            return strs[left]
        }

        val mid = (left + right) / 2
        return divideAndConquer(strs, left, mid).compare(divideAndConquer(strs, mid + 1, right))
    }

    private fun String.compare(s: String): String {

        val min = minOf(this.length, s.length)

        return (0 until min)
                .firstOrNull { this[it] != s[it] }
                ?.let { this.substring(0, it) }
                ?: this.substring(0, min)
    }
}

长度二分

class Solution {

    fun longestCommonPrefix(strs: Array<String>): String {

        if (strs.isEmpty()) {
            return ""
        }

        var minLen = Int.MAX_VALUE
        for (s in strs) {
            minLen = minOf(minLen, s.length)
        }

        var left = 0
        var right = minLen
        var mid: Int
        var len = 0

        while (left <= right) {

            mid = (left + right) / 2

            if (isCommonPrefix(strs, mid)) {
                len = mid
                left = mid + 1
            } else {
                right = mid - 1
            }
        }

        return strs[0].substring(0, len)
    }

    private fun isCommonPrefix(strs: Array<String>, len: Int): Boolean {

        (1 until strs.size)
                .firstOrNull { !strs[0].regionMatches(0, strs[it], 0, len) }
                ?.let { return false }
                ?: return true
    }
}

前缀树

class Solution {

    fun longestCommonPrefix(strs: Array<String>): String {

        if (strs.isEmpty()) {
            return ""
        }

        val trie = Trie()
        for (s in strs) {
            trie.insert(s)
        }

        return trie.searchLongestPrefix(strs[0])
    }

    class TrieNode {

        private val links: Array<TrieNode?> = arrayOfNulls(26)
        var isEnd: Boolean = false
        var size: Int = 0
            private set

        fun getTrieNode(c: Char): TrieNode? {
            return links[c - 'a']
        }

        fun setTrieNode(c: Char, node: TrieNode) {
            links[c - 'a'] = node
            size++
        }

        fun containNode(c: Char): Boolean {
            return links[c - 'a'] != null
        }
    }

    class Trie {

        private val root = TrieNode()

        fun insert(s: String) {

            var node = root

            for (c in s) {

                if (!node.containNode(c)) {
                    node.setTrieNode(c, TrieNode())
                }

                node = node.getTrieNode(c)!!
            }

            node.isEnd = true
        }

        fun searchLongestPrefix(s: String): String {

            var node = root
            val result = StringBuilder()

            for (c in s) {

                if (node.containNode(c) && node.size == 1 && !node.isEnd) {
                    result.append(c)
                    node = node.getTrieNode(c)!!
                } else {
                    return result.toString()
                }
            }

            return result.toString()
        }
    }
}

results matching ""

    No results matching ""