我们可以说 O(n + m) 等价于 O(n),当 m 是常数或当 n > m

Can we say O(n + m) is equivalent to O(n), when m is constant or when n > m

我正在解决我所在的 leetcode 问题之一(最长回文)

1.使用 array

实现
   public int longestPalindrome(String s) {

    int[] charFreq = new int[58];
    for(char sChar : s.toCharArray()){
      ++charFreq[sChar - 'A'];
    }

    int charsWithOddFreq = 0;
    for(int freq : charFreq){
      if((freq & 1) != 0){
        charsWithOddFreq++;
      }
    }

    int len = s.length();
    return (charsWithOddFreq == 0) ? len : (len - charsWithOddFreq + 1);
  }

其中,1 <= s.length <= 2000
s consists of lowercase and/or uppercase English letters only.

但是,说上面这个程序的时间复杂度是 O(n + m) 是正确的吗,这里 n is the length of the given string(s)m is the size of array taken to store frequency(charFreq) 还是只说 O(n) 更好,因为我们可以忽略常数因子 (m),它不依赖于输入字符串的大小,并且每个输入的迭代将始终相同(即 58)。
简而言之,在这种情况下是O(n + m) ~ O(n)吗?

2。使用 Map

实现相同
public int longestPalindrome(String s) {

    Map<Character, Integer> charFreq = new HashMap<>();
    for(char sChar : s.toCharArray()) {
      charFreq.put(sChar, charFreq.getOrDefault(sChar, 0) + 1);
    }

    int charWithOddFreq = 0;
    for(int val : charFreq.values()) {
      if((val & 1) != 0) {
        ++charWithOddFreq;
      }
    }

    int len = s.length();
    return (charWithOddFreq == 0) ? len : (len - charWithOddFreq + 1);
  }

使用 Map,时间复杂度应为 O(n + m),因为 m 因输入字符串而异,因为它取决于输入大小。但是,在这种情况下(使用 Map 时)我的问题是,当 n > m 时,我们可以说 O(n + m)O(n) 吗?因为根据约束,即
1 <= s.length <= 2000
s consists of lowercase and/or uppercase English letters only.
所以,字符串的长度(n) > 大小写字母的个数(m) 总之,O(n + m) ~ O(n)也是这样吗?

A1。由于 m 在您的第一个算法中是常数 (58),因此这是 O(n) 时间。此 O(n + constant)O(n) 相同。

A2。你的第二个算法也是O(n)

Using Map, the time complexity should be O(n + m), as m will vary for input string as it is dependent on the input size.

您没有明确说明,但在这种情况下,ns 中的字符数,而 m 是 [= 中的不同字符数16=].

那些可变变量mn不是独立的。事实上 m 总是小于或等于 n 而不是 n.

m + n <= 2nO(2n)O(n)相同。所以 O(m + n) 在这种情况下与 O(n) 相同。


(以上不是严格的证明......但它应该足以突出你推理中的缺陷。如果你想要严格的证明,它非常简单,尽管很乏味。)


并在(更正的)标题中回答您的问题:

Can we say O(n + m) is equivalent to O(n), when m is constant or when n > m

是的。见上。


请注意,两个版本具有相同的(时间)复杂度这一事实并不意味着它们的性能相同。

我完全同意 ,但会更进一步。 由于输入大小有上限,因此两种算法都是 O(1) - 因为对于所有有效输入,有一个恒定的操作数,两种算法都不会超过。

询问使用数组或映射的算法的渐近 worst-case time-complexity(又名 Big-O)是否最好没有意义,除非这些映射的大小可以增长超过显着范围。

我真的建议尝试绘制出每种算法对各种(有效)输入所需的时间差异。您应该会发现,对于如此小的输入,两者的表现非常相似,并且根据输入大小的时间增长非常小。由于地图的复杂性,我希望 array-based 更快;但是同样,对于这样的小问题,就原始毫秒而言,差异不会很明显。