【问题标题】:Coding brain teaser to update an array (language agnostic)编码脑筋急转弯以更新数组(与语言无关)
【发布时间】:2009-09-04 12:29:00
【问题描述】:

全部,

我需要一种聪明的方法来尽可能快速、干净地实现这个算法(用于工作): 我想我已经删除了所有特定于语言的问题并将其归结为:

我有两个数组:A 和 B。

A 中有一个名称列表 {Apple, Apple, Banana, Banana, Banana, Carrot, ...} 每个第 i 个值在 A 中出现的次数没有上限。可以只是一个“苹果”或无数个。

A 中的每个条目在 B 中都有一个匹配的条目。(多对多映射)。例如:

A[0] = "Apple"      B[0] = "0027"
A[1] = "Apple"      B[1] = "0028"
A[2] = "Banana"     B[2] = "0073"
A[3] = "Banana"     B[3] = "0041"
A[4] = "Banana"     B[4] = "0069"

如果 A 中有 100 个或更少的条目实例(如果有

例如,如果有 102 个苹果

A[0]   = "Apple"       B[0]   = "0027"
A[1]   = "Apple"       B[1]   = "0028"
...
A[99]  = "Apple"       B[99]  = "0073"
A[100] = "Apple"       B[100] = "0041"
A[101] = "Apple"       B[101] = "0069"
A[102] = "Banana"      B[102] = "0123"

那么我想要的结果是这样的:

A[0]   = "Apple"       B[0]   = "0027"
A[1]   = "Apple"       B[1]   = "0027"
...
A[99]  = "Apple"       B[99]  = "0027"
A[100] = "Apple"       B[100] = "0041"
A[101] = "Apple"       B[101] = "0041"
A[102] = "Banana"      B[102] = "0123"

我敢肯定有一些超级大脑可以想出我设计的蹩脚算法,所以让我们看看吧!

编辑 1: 我想我应该指出这是 工作。我认为这是一个有趣的挑战,有人可能会想看看,并且可能会想出比我想出的解决方案更好的解决方案。

编辑 2:感谢 daniel 指出我的愚蠢错误。

我的解决方案只是为了比较(伪代码):

首先制作 B 的哈希/字典,称为 d,其中 d[ "Apple" ] = A 中 Apple 的实例数。

while (i < A.count)
{
    string cmp = A[i];
    int v = d[cmp];
    int j=i;

    while (v--) {
       B[j++] = B[i];

       if (j %100 == 0)
       i += j
    }
    i+= d[cmp];
}

凭记忆这样做,希望我没有搞砸索引...

【问题讨论】:

  • 那么,你需要这个来工作并将其标记为“有趣”、“拼图”和“挑战”吗?而且您可能不愿意为此付出任何代价?我没听错吗?
  • 老兄,我已经解决了。我只是觉得其他人可能有更好的东西。有些人确实喜欢这类谜题/挑战——至少我喜欢。
  • 你的 A 数组是否总是排序的,就像你在例子中展示的那样?如果是这样 - 没有任何挑战...... :(
  • Apple => i = 0 => B[i + 101] = B[101] = "0069",而不是 "0041"。是我错了还是你错了?
  • 还是说,第 0...99 项获得第 0 项的值,其余第 100 项...* 获得第 100 项的值?

标签: algorithm puzzle code-golf


【解决方案1】:

就我理解问题并假设数组已排序而言,我在 C# 中的建议。

String[] A = GetAs();
String[] B = GetBs();

Int32 count = 0;
Int32 index = 1;

while (index < A.Length)
{
   if (A[index] != A[index - 1])
   {
      count = 0;
   }

   currentCount++;

   if ((A[index] == A[index - 1]) && (count % 100 != 1))
   {
      B[index] = B[index - 1];
   }

   index++;
}

如果有人喜欢它紧凑(并且从零开始计数)。

String[] A = GetAs();
String[] B = GetBs();

Int32 c = 0, i = 1;

while (i < A.Length)
{
   c = (A[i] == A[i - 1]) ? c + 1 : 0;

   B[i] = ((A[i] == A[i - 1]) && (c % 100 != 0)) ? B[i - 1] : B[i];

   i++;
}

【讨论】:

  • 我认为 currentCount %100 == 1 而不是 currentCount == 101。如果连续有 202 个苹果会怎样?
  • 将行为更正为模 100。
  • c = (A[i] == A[i - 1]) ? c + 1 : 0; 可能是 c = (A[i] == A[i - 1]) * (c + 1); - 保存一个分支
【解决方案2】:

我想建立一个字典/哈希表,比如

{'Apple':
    {'NumberSeen':102,
     'BValues':['0027','0041']
    },
 'Banana':
    {'NumberSeen':1,
     'BValues':['0123']
    }
}

然后循环遍历它,如果 NumberSeen%100 = 1 则添加一个新的 b 值,然后从该字典重新创建 B 数组。

编辑:这将为您提供一个处理未排序列表的可读解决方案。我刚刚看到您的“列表已排序”评论,这意味着您可以在 O(1) 空间中更简单地执行此操作,但我不确定代码有多清晰。

【讨论】:

    【解决方案3】:
    String curFruit = A[0];
    int curFruitCount = 0;
    for (int i = 1; i < A.length; i++) {
        if (A[i].equals(curFruit) && curFruitCount < 100) {
            B[i] = B[i-1];
            curFruitCount++;
        }else{
            curFruit = A[i];
            curFruitCount = 1;
        }
    }
    

    【讨论】:

      【解决方案4】:

      我非常喜欢 Daniel Brückner 的解决方案,但我认为您或许可以对其进行改进。假设 'A's 已排序并且 100 个连续相同的水果是常见的,那么您可以通过添加以下检查来利用它:

      String[] A = GetAs();
      String[] B = GetBs();
      Int32 c = 0, i = 1;
      while (i < A.Length)
      {   
          if(i+99 < A.Length && A[i] == A[i+99])
          {
              for(int j=1;j<100;j++) b[i+j] = b[i];
      
              i = i+99;
          }
          else
          {
              B[i] = (A[i] == A[i - 1]) ? B[i - 1] : B[i];   
              i++;
          }
      }
      

      【讨论】:

      • 只有少于 101 项的数组才会崩溃。
      • 我知道我应该再校对一遍。我为此添加了一张支票。谢谢迪卡姆。
      猜你喜欢
      • 2020-05-04
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-07-31
      • 2017-05-30
      • 2014-08-03
      • 1970-01-01
      • 2011-02-14
      相关资源
      最近更新 更多