LeetCode | 14. Longest Common Prefix的三种算法

问题

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

Solution 1: Binary Search Using Recursion

大概的思路是:首先找到input中string的最小长度L,然后把每个string从L/2处一分为二,先比较[0, L/2]是否是common prefix。如果前一半是,则比较[L/2+1, 3/4*L];如果前一半不是,则比较[0,L/4]。

在下面这个implementation中,由于recursion完全在checkPrefix这个函数中进行,且在每一层会call这个函数两次,因此不是很efficient。

def longestCommonPrefix(self, strs: List[str]) -> str:
	try:
        n = np.min([len(word) for word in strs])
    except ValueError:
        return ''
    if n==0:
        return ''
    strs = [word[:n] for word in strs]
    re = checkPrefix(strs, l=0, r=n)
    return strs[0][:re]

def checkPrefix(self, strs, l, r):
	# stop case
    if l == r-1:
        first = strs[0]
        for word in strs:
            if word[l]!=first[l]:
                return l
        return r
    else:
        mid = l + math.ceil((r-l)/2)
        # recursive call 1
        if checkPrefix(strs, l, mid)==mid:
        	# recursive call 2
            return checkPrefix(strs, mid, r)
        else:
            return checkPrefix(strs, l, l + math.ceil((r-l)/4))
Complexity Analysis:
  • L是input中最小的string长度,S是input string长度之和,则binary search algorithm的time complexity为O(log(L)*S)。这是因为总共会做O(log(L))次comparisons,而每次比较prefix都需要O(S)。
  • Space Complexity是O(log(L)),因为总共有O(log(L))个recursive calls,而每个的存储空间是O(1)。

Solution 2: Iterative Binary Search

改进后的implementation不使用recursion,而是用lr两个pointers,且在checkPrefix函数只进行prefix的比对。这样的速度快了很多:

def longestCommonPrefix(self, strs: List[str]) -> str:
        try:
            n = np.min([len(word) for word in strs])
        except ValueError:
            return ''
        if n==0:
            return ''
        strs = [word[:n] for word in strs]
        l = 0
        r = n - 1
        while l<=r:
            mid = math.ceil((l + r)/2)
            if checkPrefix(strs, l, mid):
                l = mid + 1
            else:
                r = mid - 1
        return strs[0][:r+1]
    
    def checkPrefix(self, strs, l, r):
        first = strs[0][l:r+1]
        for word in strs:
            if first!=word[l:r+1]:
                return False
        return True
Complexity Analysis:
  • Time complexity同上,O(log(L)*S)。
  • Space Complexity O(1)。

Solution 3: Vertical Scanning

思路很简单:把input的所有词竖着排列起来,从最左边开始,每次比较一个character。

(其实仔细分析一下,vertical scanning应该是最intuitive、最好implement、同时还最快的algorithm了,不知道为什么自己的第一反应是舍近求远去弄最不方便的recursive binary search……)

# deal with edge cases
try:
    n = np.min([len(word) for word in strs])
except ValueError:
    return ''
if n==0:
    return ''
if len(strs)==1:
    return strs[0]
strs = [word[:n] for word in strs]
# start scanning
for i in range(n):
    first = strs[0][i]
    for word in strs[1:]:
        if word[i]!=first:
            return strs[0][:i]
return strs[0]
Complexity Analysis
  • Time complexity O(S),因为worst case不过是把input里的所有character都比对一遍罢了。
  • Space complexity O(1)。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值