【问题标题】:Codility ChallengeCodility 挑战
【发布时间】:2024-11-28 22:30:02
【问题描述】:

我正在尝试完成编码挑战以提高我的编程技能,或者说缺乏它。挑战详情在这里。

在一个房间里有 N 根绳索和 N 个重物。每根绳子都连接到 正好有一个重量(只有一端),每根绳子都有一个特定的重量 耐久性 - 它可以暂停的最大重量。还有一个 挂钩,固定在天花板上。绳索可以连接到钩子上 通过在没有重量的情况下捆绑末端。绳索也可以固定在 其他重量;也就是说,绳索和重物可以连接到一个 链中的另一个。如果重量的总和相连,绳子就会断裂 对它来说,直接或间接地,大于它的持久性。

我们知道要连接 N 根绳索的顺序。更确切地说, 我们知道绳索的参数(耐用性和重量)和 每个附件的位置。耐久性、重量和位置是 在长度为 N 的三个零索引数组 A、B、C 中给出。对于每个 I (0 ≤ I

A= [4,3,1]
B = [2,2,1]
C = [-1,0,1]

函数应该返回 2,就好像我们连接第三根绳子然后一根绳子会断裂,因为权重的总和大于它的 耐久性(2 + 2 + 1 = 5 和 5 > 4)。

下面是我尝试的解决方案。我有一个名为 add_weights 的辅助函数,如果添加最新的绳子不会导致任何其他绳子断裂,则返回 True,否则返回 false。

def add_weights(A, ancestors, weights, weight, rope):
    #add weight(int) to rope and ancestors
    if (rope == -1):
        return (True)
    else:
        weights[rope] += weight
        if (A[rope] < weights[rope]):
            print "Rope that breaks", rope
            return False
        ancestor = ancestors[rope]
        print ancestor
        add_weights(A, ancestors, weights, weight, ancestor)




def solution(A, B, C):
    # write your code in Python 2.7
    weights = {}
    ancestors = {}
    for i in range(len(B)):
        weights[i] = B[i]
    for i in range(len(C)):
        #attaching rope i to rope x
        x = C[i]
        ancestors[i] = x
        broke = add_weights(A, ancestors, weights, B[i], x)
        if (not broke):
            return i
    return len(C)

问题是在函数解决方案中 for 循环的第二次迭代期间(当我尝试添加绳索 1 时),当我可以清楚地看到 add_weights 返回 True 时,变量 break 以某种方式计算为 None。我也用调试器对其进行了测试,所以我不完全确定发生了什么。欢迎任何帮助。

【问题讨论】:

  • 请想出一个更好的问题标题;你现在的那个没有告诉我们你的问题。对我们而言,您的问题源自何处并不重要。
  • add_weights 在基本情况下只有一个return - 将最后一行设为return add_weights(...)
  • 我还是想知道为什么在他们的例子中答案是 2。

标签: python arrays algorithm


【解决方案1】:

这是我的第一个解决方案 O(N**2),它只是通过绳索运行并减轻每个连接的绳索的重量。

  def solution(A, B, C):
    num_ropes = len(C)

    for i in range(num_ropes):
      node = i
      while(node != -1):
        A[node] -= B[i]
        if A[node] < 0:
          return i
        node = C[node]
    return num_ropes

这是 O(N*log(N)) 的解决方案,其原理是,它不是穿过所有绳索,而是穿过具有一个张力的绳索组。

  def solution(A, B, C):
    num_ropes = len(C)

    for i in range(num_ropes):
      A[i] -= B[i]
      if A[i] < 0:
        return i

      pre_node = C[i]
      while pre_node != -1:
        A[pre_node] -= B[i]
        if A[pre_node] < 0:
          return i

        if A[pre_node] <= A[i]:
          C[i] = pre_node
          A[i] = A[pre_node]
        pre_node = C[pre_node]

    return num_ropes

可以使用最后一部分或https://app.codility.com/programmers/challenges/sulphur2014/进行测试

  if __name__ == '__main__':
    A = [5, 3, 6, 3, 3]
    B = [2, 3, 1, 1, 2]
    C = [-1, 0, -1, 0, 3]
    assert solution(A, B, C) == 3

    A = [4, 3, 1]
    B = [2, 2, 1]
    C = [-1, 0, 1]
    assert solution(A, B, C) == 2

【讨论】:

    【解决方案2】:

    我没有时间把它翻译成 Python,但你可以看看这个 JS 代码有个想法:

    function keysOrderedByValues(array) {
        var result = [];
        for (var i = 0; i < array.length; i++) {
            result[array[i] + 1] = i;
        }
        return result;
    }
    
    function findFirstPositiveElem(array) {
        for (var i = 0; i < array.length; i++) {
            if (array[i]>0) {
                return i;
            }
        }
        return null;
    }
    
    function accumulativeArray(array) {
        var result = [];
        var sum = 0;
        for (var i = 0; i < array.length; i++) {
            sum = sum + array[i];
            result.push(sum);
        }
        return result;
    }
    
    Array.prototype.indexedByArray = function(array) {
        result = [];
        for (var i = 0; i < array.length; i++) {
            result.push(this[array[i]])
        }
        return result;
    }
    
    function test(ds, ws, ords) {
        return findFirstPositiveElem(ws.indexedByArray(keysOrderedByValues(ords)), ds);
    }
    
    console.log(test([4,3,1], [2,2,1], [-1,0,1]))
    

    【讨论】:

      【解决方案3】:

      忘了说:这是 O(n) 和数组 B2 的一些空间复杂度

          int Solution (int[]A, int[] B, int[] C)
          {
              if (A==null || B==null || C==null)
                  return -1;
              if (A.Length==0 || B.Length==0 || C.Length==0)
                  return -1;
              if (A.Length != B.Length && A.Length != C.Length)
                  return -1;
      
      
              var bLen=B.Count();
              var B2 = new int[bLen];
              for (int i = 0; i < bLen; i++)
                  B2[i]=(i==0? 0 : B2[i-1]) + B[i]; //cumulative sum
      
      
              var ret=-1;
              var skip=0;
              for (int i = 0; i < A.Length; i++)
              {
                  skip=C[i]+1;
                  if (A[i] - (B2[bLen-1] - (skip>0 ? B2[skip-1] : 0)) < 0) 
                  {
                      ret=bLen-skip-1;
                      break;
                  }
              }
              return ret;
          }
      

      【讨论】:

      • 这个解决方案对我不起作用。 A=[5, 3, 6, 3, 3] B=[2, 3, 1, 1, 2] C=[-1, 0, -1, 0, 3]。返回 4 根绳索而不是 3 根绳索。我还必须将B.Count() 更改为B.Length
      【解决方案4】:
      using System;
      using System.Collections.Generic;
      using System.Linq;
      using System.Text;
      using System.Threading.Tasks;
      
      namespace Exercise5_DurablityofRopes
      {
          class Program
          {
                 static int[] A_Durability = new int[] { 15, 6, 2,3,1 };
                 static int[] B_Weight = new int[] { 2, 1, 2,3,1 };
                 static int[] C_Position = new int[] { -1, 0, 1 ,2,3};
                 static int no_of_ropes_attached = 0;
                 static int maxropeattached = 0;
                 static void Main(string[] args)
              {
                 // first position cannot necessarily be -1 hence Checking for each position How many maximum ropes can be attached
                  for (int i = 0; i <= C_Position.Length - 1; i++)
                  {
                      int[] Copy_Durability = new int[A_Durability.Length];
                      for (int l = 0; l <= C_Position.Length - 1; l++)
                      {
                          Copy_Durability[l] = A_Durability[l];
                      }
                      AddNextRope(i, B_Weight[i], Copy_Durability);          
                      Console.WriteLine("Total Number of ropes can be attached to " + C_Position[i] + " ropes are" + no_of_ropes_attached);
                      if (no_of_ropes_attached>=maxropeattached)
                      {
                          maxropeattached = no_of_ropes_attached;
                      }
                      no_of_ropes_attached = 0;
                  }
      
                  Console.WriteLine("Total Number of ropes can be attached is  " + maxropeattached);
                  Console.ReadKey();
              }
      
              private static void AddNextRope(int currentRopePosition,int newWeight,int[] Durability)
              {
                  if (currentRopePosition == C_Position.Length - 1) return;
                  // decrease same amount of weight from all ansestors from their durability and check if any of them breaks (durability <0) with new weight added
                  for (int k = currentRopePosition; k != 0; k--)
                  {
                      Durability[k] = Durability[k] - newWeight;
                      if(Durability[k]<0)
                      {
                          return;
                      }
                  }
                  no_of_ropes_attached = no_of_ropes_attached + 1; 
      
                  for (int i = 0; i <= C_Position.Length - 1; i++)
                      {
                          if (C_Position[i] == C_Position[currentRopePosition] + 1)
                          {
                              if (A_Durability[i] > B_Weight[i])
                              {
                                  AddNextRope(i, B_Weight[i], Durability);
                              }
                              else
                              {
                                  return;
                              }
                          }
                      }
              }
          }
      }
      

      【讨论】: