leetcode
leetcode 2751 ~ 2800
最长公共前缀的长度

最长公共前缀的长度

难度:

标签:

题目描述

You are given two arrays with positive integers arr1 and arr2.

A prefix of a positive integer is an integer formed by one or more of its digits, starting from its leftmost digit. For example, 123 is a prefix of the integer 12345, while 234 is not.

A common prefix of two integers a and b is an integer c, such that c is a prefix of both a and b. For example, 5655359 and 56554 have a common prefix 565 while 1223 and 43456 do not have a common prefix.

You need to find the length of the longest common prefix between all pairs of integers (x, y) such that x belongs to arr1 and y belongs to arr2.

Return the length of the longest common prefix among all pairs. If no common prefix exists among them, return 0.

 

Example 1:

Input: arr1 = [1,10,100], arr2 = [1000]
Output: 3
Explanation: There are 3 pairs (arr1[i], arr2[j]):
- The longest common prefix of (1, 1000) is 1.
- The longest common prefix of (10, 1000) is 10.
- The longest common prefix of (100, 1000) is 100.
The longest common prefix is 100 with a length of 3.

Example 2:

Input: arr1 = [1,2,3], arr2 = [4,4,4]
Output: 0
Explanation: There exists no common prefix for any pair (arr1[i], arr2[j]), hence we return 0.
Note that common prefixes between elements of the same array do not count.

 

Constraints:

  • 1 <= arr1.length, arr2.length <= 5 * 104
  • 1 <= arr1[i], arr2[i] <= 108

代码结果

运行时间: 144 ms, 内存: 29.0 MB


/*
题目思路:
1. 使用 Java Stream 遍历两个数组的所有数对。
2. 对每一个数对计算公共前缀长度。
3. 找出最长的公共前缀长度。
*/

import java.util.Arrays;

public class LongestCommonPrefixStream {
    public int longestCommonPrefix(int[] arr1, int[] arr2) {
        return Arrays.stream(arr1)
                      .flatMap(x -> Arrays.stream(arr2).mapToObj(y -> commonPrefixLength(x, y)))
                      .max(Integer::compareTo)
                      .orElse(0);
    }

    private int commonPrefixLength(int x, int y) {
        String s1 = String.valueOf(x);
        String s2 = String.valueOf(y);
        int minLength = Math.min(s1.length(), s2.length());
        int length = 0;
        for (int i = 0; i < minLength; i++) {
            if (s1.charAt(i) == s2.charAt(i)) {
                length++;
            } else {
                break;
            }
        }
        return length;
    }

    public static void main(String[] args) {
        LongestCommonPrefixStream lcp = new LongestCommonPrefixStream();
        int[] arr1 = {1, 10, 100};
        int[] arr2 = {1000};
        System.out.println(lcp.longestCommonPrefix(arr1, arr2));  // 输出: 3
    }
}

解释

方法:

这个问题的解决方案首先是构建两个集合s1和s2,用于存储arr1和arr2中所有可能的前缀。对于每个元素,我们通过逐步除以10(去掉最右边的数字)来获取所有前缀,并将其添加到相应的集合中。这样,每个集合都会包含其数组中所有数字的所有前缀。接下来,我们取两个集合的交集,找出同时出现在两个数组中的前缀。最后,从交集中选择最长的前缀(如果存在的话),并返回其长度。如果交集为空,说明没有公共前缀,返回0。

时间复杂度:

O(n)

空间复杂度:

O(n)

代码细节讲解

🦆
代码中提到的集合s1和s2有没有可能包含重复前缀?如果有,这会影响算法的正确性和效率吗?
在代码中,s1和s2是集合数据结构,它们的特性是自动去除重复元素。因此,即使尝试多次添加相同的前缀,集合仍然只保留一个。这样,不会有重复的前缀存在于集合中。这种特性有助于保持集合的唯一性,不会影响算法的正确性。同时,使用集合可以避免重复检查,从而在一定程度上提高效率。
🦆
在构建前缀集合时,为什么要继续添加前缀直到`x为0`?是否有更高效的方式来确定一个数字的所有有效前缀?
构建前缀集合时,继续添加前缀直到`x为0`是为了确保捕获从最长到最短的所有可能前缀。这种方法简单且直接,确保了所有前缀都被考虑。然而,对于提高效率,一种可能的方法是在添加前缀前先检查这个前缀是否已经存在于集合中,如果存在,则不再继续对该数字进行处理。这样可以减少不必要的除法和添加操作,尤其是在处理较大数字时。
🦆
如何处理输入数组中的边界情况,例如数组为空或数组中的所有元素都是相同的数字?
对于数组为空的情况,应在函数开始时进行检查。如果任一数组为空,则没有公共前缀,应立即返回0。对于数组中所有元素都是相同的数字的情况,由于这些元素具有相同的前缀,所以最长公共前缀就是任一元素本身的长度。因此,这种情况下算法仍然有效,可以正确返回最长公共前缀的长度。

相关问题