挑选数字-解决Ruby中的黑客等级挑战 问题解释

挑选数字-解决Ruby中的黑客等级挑战 问题解释,ruby,Ruby,给定一个整数数组,找出任意两个元素之间的绝对差小于或等于1的最长子数组 范例 a=[1,1,2,2,4,4,5,5] 有两个子阵列满足标准:[1,1,2,2]和[4,4,5,5,5]。最大长度子阵列有5个元素 PickingNumber具有以下参数: int a[n]:整数数组 返回 int:满足条件的最长子数组的长度 我试过的 def选取编号(a) #在这里编写代码 a、 排序! 当前计数器=0 最大计数器=0 i=0 而我穿的是a码 j=1 while(a[j].to_int-a[i

给定一个整数数组,找出任意两个元素之间的绝对差小于或等于1的最长子数组

范例 a=[1,1,2,2,4,4,5,5] 有两个子阵列满足标准:[1,1,2,2]和[4,4,5,5,5]。最大长度子阵列有5个元素

PickingNumber具有以下参数:

  • int a[n]:整数数组
返回

  • int:满足条件的最长子数组的长度
我试过的
def选取编号(a)
#在这里编写代码
a、 排序!
当前计数器=0
最大计数器=0
i=0
而我穿的是a码
j=1
while(a[j].to_int-a[i].to_int)max\u计数器
结束
i+=1
结束
最大值计数器
结束
输入=[1,1,2,2,4,4,5,5]
选取编号(输入)
请求: 为什么上面的代码不起作用?如果有人能解释一下,我将不胜感激。 我正在学习解决算法方面的挑战,我知道有几十种更好的解决方案。不过,我还是想知道为什么这段代码不起作用!)
提前感谢

您正在检查以确保
i
但是您没有对
j
执行相同的操作

最后,将j增加到数组大小之外,并尝试访问返回nil的
a[9]

nil.to_int
是导致错误的原因(尽管您没有实际说明您在问题中看到的错误)

在Ruby中迭代数组的更多方法是使用
.each
,这避免了此类错误


我还建议不要使用
.sort
bang操作符警告您这是在修改原始数组。

我有一个例程,将数组拆分为多个组,[1,1,2,2,3,3,3]将是两个数组[1,1,1,2,2,2]和[3,3,3]

显然,如果这是针对hackerrank的,你需要看看它是否足够快

如果你想要一条糟糕的单行线:

a.sort.inject({}) {|x,y| x.key?(y-1) ? x[y-1] << y : (x[y]||=[] ; x[y] << y) ; x}.values.map(&:count).max
a.sort.inject({}){x,y{x.key?(y-1)?x[y-1]这里有一种解决方法,它的时间复杂度更高,可以避免使用两个循环
我知道可以做的修改很少(如使用三元运算符等)。如果您有想法,欢迎使用水泥

def选取编号(a)
#在这里编写代码
a、 排序!
当前计数器=1
最大计数器=0
参考检查程序=a[0]
i=1
而我穿的是a码
if(一个[i]-参考检测器)最大计数器
当前计数器=1
结束
i+=1
结束
如果当前计数器<最大计数器
最大值计数器
其他的
电流计数器
结束
结束
输入=[1,1,2,2,4,4,5,5]
p选取编号(输入)
我的单人表演团队的荣誉)


这里有两种解决问题的方法,一种很容易编码,另一种更复杂,但我认为应该更快,可能更快

a1 = [1,1,2,3,4]
a2 = [1,1,2,2,4,4,5,5,5]
a3 = [1,1,3,2,4,4,5,5,7,6,5,6,5,4,3,4,5,7,8]
代码不多,但速度可能足够快

def quick_n_dirty(arr)
  arr.size.downto(1).each do |n|
    arr.each_index.each_cons(n) do |a|
      mn, mx = a.map { |i| arr[i] }.minmax
      return { start: a.first, end: a.last } if mx <= mn + 1
    end
  end
end

考虑包含五个元素的
a1
。首先查看整个阵列是否满足要求,在这种情况下,我们将完成:

enum = a1.each_cons(5)
  #=> #<Enumerator: [1, 1, 2, 3, 4]:each_cons(5)>
它只生成一个元素,
a1
本身:

a = enum.next
  #=> [1, 1, 2, 3, 4]
b, c = a.minmax 
  #=> [1, 4]
< > >代码>(C-B)。ABS=3 < /代码>和<代码> 3 > 1 <代码>,我们看到<代码> A1 < /代码>不符合要求。现在考虑所有子数组的大小<代码> 4 < /代码>。如果发现有希望的属性,我们就完成了。

enum = a1.each_cons(4)
  #=> #<Enumerator: [1, 1, 2, 3, 4]:each_cons(4)>
enum.to_a
  #=> [[1, 1, 2, 3], [1, 2, 3, 4]]
a = enum.map { |arr| arr.minmax }
  #=> [[1, 3], [1, 4]]
b = a.map { |x,y| (y-x).abs }
  #=> [2, 3]
b.find { |diff| diff <= 1 }
   #=> nil
!我们发现子阵列
[1,1,2]
满足要求,所以我们完成了

这就是我的代码所做的,只是它返回一个散列,显示具有所需属性的最大子数组的开始和结束(或者我应该说“a”,而不是“the”,因为可能有联系)。(在重新阅读问题时,似乎只需要最大子数组的长度,允许稍微简化。)

如果
n=arr.size
,在最坏的情况下,必须检查的子阵列数等于
n+(n-1)+(n-2)+…+2+1
,这等于
n*(n+1)/2

更多代码,但速度应该更快

def should_be_faster(arr)
  a = arr + [Float::INFINITY]
  current = { early: 0, late: nil }
  a.each_with_index.with_object({ start: 0, end: 0 }) do |(n,i), longest|
    next if i.zero?               
    curr_val = a[i]
    curr_early_val = a[current[:early]]
    curr_late_val = current[:late].nil? ? nil : a[current[:late]]
    if current[:late].nil?
      case curr_val - curr_early_val
      when 0
      when 1, -1
        current[:late] = i
      else
        update_if_improvement(current, longest, i)
        current[:early] = i
        current[:late] = nil
      end
    elsif curr_val != curr_early_val && curr_val != curr_late_val
      update_if_improvement(current, longest, i)
      if (curr_val - curr_late_val).abs == 1
        current[:early] = current[:late]
        current[:late] = i
      else
        current[:early] = i
        current[:late] = nil
      end
    end
  end
end

未定义nil:NilClass的方法“to_int”
,原因由Matthew在下面解释。算法提示:查看“为什么上面的代码不起作用?”不是一个足够精确的错误描述,我们无法帮助您。什么不起作用?它如何起作用?您的代码有什么问题?您是否收到错误消息?错误消息是什么?您得到的结果是否不是您期望的结果?您期望的结果是什么?为什么,您得到的结果是什么,以及如何处理两种不同?你观察到的行为不是期望的行为吗?期望的行为是什么,为什么,观察到的行为是什么,它们有什么不同?你能提供到黑客银行问题的链接吗?如果我的理解是正确的,你想要一个
a
的子数组,它是
a[i..j]形式的数组
,所以我不知道如何排序
a
挑选数字[1,1,3,2,4,4,5,5,7,6,5,5,4,3,4,5,7,8]#=>7,但我没有看到大小大于4的合格子数组。如果时间允许,我将为解决方案2提供解释。
enum = a1.each_cons(5)
  #=> #<Enumerator: [1, 1, 2, 3, 4]:each_cons(5)>
enum.to_a
  #=> [[1, 1, 2, 3, 4]]
a = enum.next
  #=> [1, 1, 2, 3, 4]
b, c = a.minmax 
  #=> [1, 4]
enum = a1.each_cons(4)
  #=> #<Enumerator: [1, 1, 2, 3, 4]:each_cons(4)>
enum.to_a
  #=> [[1, 1, 2, 3], [1, 2, 3, 4]]
a = enum.map { |arr| arr.minmax }
  #=> [[1, 3], [1, 4]]
b = a.map { |x,y| (y-x).abs }
  #=> [2, 3]
b.find { |diff| diff <= 1 }
   #=> nil
enum = a1.each_cons(3)
  #=> #<Enumerator: [1, 1, 2, 3, 4]:each_cons(3)>
enum.to_a
  #=> [1, 1, 2], [1, 2, 3], [2, 3, 4]]
a = enum.map { |arr| arr.minmax }
  #=> [[1, 2], [1, 3], [2, 4]]
b = a.map { |x,y| (y-x).abs }
  #=> [1, 2, 2]
b.find { |diff| diff <= 1 }
  #=> 1
def should_be_faster(arr)
  a = arr + [Float::INFINITY]
  current = { early: 0, late: nil }
  a.each_with_index.with_object({ start: 0, end: 0 }) do |(n,i), longest|
    next if i.zero?               
    curr_val = a[i]
    curr_early_val = a[current[:early]]
    curr_late_val = current[:late].nil? ? nil : a[current[:late]]
    if current[:late].nil?
      case curr_val - curr_early_val
      when 0
      when 1, -1
        current[:late] = i
      else
        update_if_improvement(current, longest, i)
        current[:early] = i
        current[:late] = nil
      end
    elsif curr_val != curr_early_val && curr_val != curr_late_val
      update_if_improvement(current, longest, i)
      if (curr_val - curr_late_val).abs == 1
        current[:early] = current[:late]
        current[:late] = i
      else
        current[:early] = i
        current[:late] = nil
      end
    end
  end
end
def update_if_improvement(current, longest, i)
  if i - current[:early] > longest[:end] - longest[:start] + 1
    longest[:start] = current[:early]
    longest[:end] = i-1
  end
end
should_be_faster(a1)
  #=> {:start=>0, :end=>2}
should_be_faster(a2)
  #=> {:start=>4, :end=>8}
should_be_faster(a3)
  #=> {:start=>4, :end=>7}