【问题标题】:Efficient algorithm to find the sum of all concatenated pairs查找所有连接对之和的高效算法
【发布时间】:2020-10-05 09:22:30
【问题描述】:

我参加了 CodeSignal 练习考试,并且能够通过 14/16 的测试用例来解决这个问题。给你一个向量作为输入(整数列表),解决方案会很长。

最初我只是简单地使用了两个 for 循环的蛮力解决方案,并将当前的 a[i] concat a[j] 添加到运行总数中。但是,我尝试通过使用 memoization 来优化它。我使用了一个 unordered_map 对来检查我是否已经计算了 (i,j) 对,如果是,则简单地返回缓存的结果。即使进行了优化,我仍然没有通过任何额外的测试用例并收到 14/16 的结果。我缺少什么见解或优化?

我发现了类似的在线问题,但他们的见解似乎不适用于这个特定问题。

例如:Similar Problem

问题:

给定一个正整数数组a, 你的任务是计算所有可能的 concat(a[i], a[j]) 的总和,其中 concat(a[i],a[j]) 是 a[I] 和 a [j] 分别。

例如:

a = [10,2]
sol = 1344
a[0],a[0] = 1010
a[0],a[1] = 102
a[1],a[0] = 210
a[1],a[1] = 22
sum of above = 1344

代码:

long long concat(int x, int y)
{
  string str = to_string(x)+to_string(y);
  return stoll(str);
}
long long calculateSum(vector<int> a)
{
  unordered_map<pair<int,int>,long long, hash_pair> memo;
  long long total = 0;
  for(int i = 0; i < a.size(); i++)
  {
    for(int j = 0; j < a.size(); j++)
    {
      auto currPair = make_pair(a[i],a[j]);
      auto got = memo.find(currPair);
      //if it's a new combination
      if(currPair == got.end())
      {
        long long res = concat(a[i],a[j]);
        memo.insert(make_pair(currPair,res));
        total += res;
      }
      //we've computed this result before
      else
      {
        total += got->second;
      }
    }
  }
  return total;
}

【问题讨论】:

  • 请在此处发布实际问题文本。大多数人不会通过链接查看您的问题是什么,如果没有这些信息,您的问题真的无法回答。
  • 我没有带我的代码,因为一旦测试会话关闭,它就消失了。但是,如果需要或要求,我可以再次输入我的代码并发布。
  • 另外,将文本发布为文本,而不是图像。不是每个人都能看到图片
  • 会修改帖子
  • 所以,您是说您编写的代码(您没有显示)通过了 16 个测试用例中的 14 个。你想知道你错过了什么,对于另外两个?而且您认为有人可以在不查看您的程序成功计算的 14 个测试用例的情况下找出答案?

标签: c++ algorithm combinatorics


【解决方案1】:

这是一个实现 @aropan 解释的有效 Java/8-11 解决方案:

 static long solution(int[] a){
    java.util.Map<Integer,Integer> intToLength = new java.util.HashMap();
    int len = a.length;
    int[] lengths = new int[len];//track the length of each elements to avoid including it when doing the k_j*a[i]*10^j calculation.
    for(int i=0; i<len; i++){
        int l = (int)Math.log10(a[i])+1;
        lengths[i] = l;
        intToLength.compute(l, (k, v) -> v == null ? 1 : v+1);
    } 

    long sum = 0;
    for(int i=0; i<len; i++){
        sum += len*a[i];
        //k_j*a[i]*10^j calculation
        long x = 0;
        for(var e : intToLength.entrySet()){
            int k_j = 0;
            if(lengths[i] == e.getKey())
                k_j--;//exclude a[i] length
            k_j+=e.getValue();
            x += k_j*a[i]*(long)Math.pow(10, e.getKey());
        }
        sum += x;
    }
    return sum;
}

【讨论】:

    【解决方案2】:

    JS 解决方案通过了所有测试用例:

    function concatenationsSum(arr) {
       let inimSum = 0;
       let offsetSum = 0;
       arr.forEach(el => {
          inimSum += el;
    
          const size = el.toString().length;
          const offset = Math.pow(10, size);
          offsetSum += offset;
       });
    
       return inimSum * arr.length + inimSum * offsetSum;
    }
    

    【讨论】:

      【解决方案3】:

      以下 Java 解决方案通过了我认为的所有测试用例。

      long concatenationsSum(int[] a) {
          long[] ans = new long[1];
          long[] total = new long[1];
          Map<Integer, Integer> powMap = new HashMap<>();
          for(int i = 0; i < a.length; ++i){
              int currentPow = (int)Math.log10(a[i]);
              powMap.put(currentPow, powMap.getOrDefault(currentPow, 0)+1);
              total[0] += a[i];
          }
          powMap.put(-1, a.length);
          powMap.forEach((key, val)-> ans[0] +=(long)Math.pow(10, key+1)*total[0]*val);
          return ans[0]; }
      

      【讨论】:

        【解决方案4】:

        我在在线评估平台中遇到了完全相同的问题。以下 python 解决方案通过了所有测试用例。

        import collections
        def concatenatSum(a):
            tot = 0
            dic = collections.defaultdict(int)
            for i in range(len(a)):
                _str = str(a[i])
                n = len(_str)
                dic[n]+=1
            
            for i in  range(len(a)):
                for k,v in dic.items():
                    tot+=a[i]*(v*pow(10,k))
                tot+=(a[i]*len(a))
            
            return tot
        

        【讨论】:

          【解决方案5】:

          让我们计算贡献a_i整数以回答所有对。有两种情况。第一种情况是数字a_i 是低部分。当总和为n * a_i 时回答(n 是总数整数)。第二种情况是高部分。然后让我们以十进制表示法查找所有偏移量。用k_j 表示总数整数长度j(十进制表示的长度)。然后高部分添加到答案k_j * a_i * 10^j 以获取所有值j (1 &lt;= j &lt;= 7)。知道k_j 我们可以在线性时间内计算出所有数字a_i 的答案。

          【讨论】:

          • 通常计算 j 不会是线性的,但实际上整数的长度被限制在大约 10 位,所以它没有任何区别。
          • 这个答案需要更好的英语和至少一些代码。
          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2014-10-03
          • 2010-12-06
          • 2010-11-20
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多