【问题标题】:Leetcode solution of Check Array Formation Through ConcatenationLeetcode通过串联校验数组形成的解决方案
【发布时间】:2021-02-17 05:15:36
【问题描述】:

我已经测试了这个问题的基于字符串和基于地图的实现。第一个运行时间为 12 毫秒,而第二个运行时间为 1 毫秒,两者使用几乎相同的空间。两种风格的实现结构看起来是一样的。 所以,我想知道为什么两者之间存在很大的运行时差异。 以下是两种实现方式:

class Solution {
    public boolean canFormArray(int[] arr, int[][] pieces) {
        
        // string based
        String str = "";
        for (int i=0; i<arr.length; i++) {
            str = str + arr[i] + "#";
        }
        
        for (int i=0; i<pieces.length; i++) {
            String str2 = "";
            for (int j=0; j<pieces[i].length; j++) {
                str2 = str2 + pieces[i][j] + "#";
            }
            if (!str.contains(str2)) {
                return false;
            }
        }
        
        return true;
        
        // map based
        HashMap<Integer, Integer> map = new HashMap<>();
        for (int i=0; i<arr.length; i++) {
            map.put(arr[i], i);
        }
        
        for (int i=0; i<pieces.length; i++) {
            if (!map.containsKey(pieces[i][0])) {
                return false;
            }
            int index = map.get(pieces[i][0]);
            for (int j=1; j<pieces[i].length; j++) {
                if (!map.containsKey(pieces[i][j])) {
                    return false;
                }
                if (map.get(pieces[i][j]) != index+1) {
                    return false;
                }
                index++;
            }
        }
        
        return true;
    }
}

【问题讨论】:

  • HashMap.get 和 HashMap.containsKey 都是 O(1),而 String.containsKey 是 O(n)。

标签: java string hashmap


【解决方案1】:

str.contains(str2) 在最坏情况下的时间复杂度为 O(nm)。

而 map.containsKey(pieces[i][0]) 的时间复杂度为 O(1)

请同时查看此答案以了解更多详细信息 Time complexity of String.contains()

【讨论】:

    【解决方案2】:

    猜测str = str + arr[i] + "#";str2 = str2 + pieces[i][j] + "#"; 正在循环内创建新字符串。虽然创建对象不再像以前那样繁重,但最好还是避免在循环中执行此操作。

    为避免这种情况,请在循环外创建 StringBuilder,在循环内使用 append 方法,并在循环完成后使用 toString()

    【讨论】:

      【解决方案3】:
      • 类似的方法,这会在 Java 中传递:
      public class Solution {
          public static final boolean canFormArray(
              final int[] arr,
              final int[][] pieces
          ) {
              StringBuilder sb = new StringBuilder();
      
              for (int num : arr) {
                  sb.append(num);
                  sb.append("#");
              }
      
              for (int i = 0; i < pieces.length; i++) {
                  StringBuilder res = new StringBuilder();
      
                  for (int j = 0; j < pieces[i].length; j++) {
                      res.append(String.valueOf(pieces[i][j]));
                      res.append("#");
                  }
      
                  if (!sb.toString().contains(res.toString())) {
                      return false;
                  }
              }
      
              return true;
          }
      }
      
      • 更好的方法是使用HashMap,这里是 C++ 版本:
      // Most of headers are already included;
      // Can be removed;
      #include <iostream>
      #include <vector>
      #include <unordered_map>
      
      
      // The following block might slightly improve the execution time;
      // Can be removed;
      static const auto __optimize__ = []() {
          std::ios::sync_with_stdio(false);
          std::cin.tie(nullptr);
          std::cout.tie(nullptr);
          return 0;
      }();
      
      
      struct Solution {
          static const bool canFormArray(
              const std::vector<int>& arr,
              const std::vector<std::vector<int>>& pieces
          ) {
              std::unordered_map<unsigned int, std::vector<int>> starts_partitions;
      
              for (const auto& piece : pieces) {
                  starts_partitions[piece[0]] = piece;
              }
      
              std::vector<int> form_array;
      
              for (const auto& num : arr) {
                  form_array.insert(
                      std::end(form_array),
                      std::begin(starts_partitions[num]),
                      std::end(starts_partitions[num])
                  );
              }
      
              return form_array == arr;
          }
      
      };
      
      
      
      // int main() {
      
      //     std::cout <<  Solution().canFormArray({85}, {{85}}) << "\n";
      //     std::cout <<  Solution().canFormArray({15, 88}, {{88}, {15}}) << "\n";
      //     std::cout <<  Solution().canFormArray({49, 18, 16}, {{16, 18, 49}}) << "\n";
      //     std::cout <<  Solution().canFormArray({91, 4, 64, 78}, {{78}, {4, 64}, {91}}) << "\n";
      //     std::cout <<  Solution().canFormArray({1, 3, 5, 7}, {{2, 4, 6, 8}}) << "\n";
      // };
      
      • 如果我们只看 Python 版本会更容易理解:
      class Solution:
          def canFormArray(self, arr: List[int], pieces: List[List[int]]) -> bool:
              starts_pieces = {piece[0]: piece for piece in pieces}
      
              form_array = []
      
              for num in arr:
                  form_array += starts_pieces.get(num, [])
      
              return form_array == arr
      
      

      【讨论】:

        猜你喜欢
        • 2015-11-20
        • 1970-01-01
        • 1970-01-01
        • 2021-11-03
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2022-01-13
        相关资源
        最近更新 更多