挑选数字-解决Ruby中的黑客等级挑战 问题解释
给定一个整数数组,找出任意两个元素之间的绝对差小于或等于1的最长子数组 范例 a=[1,1,2,2,4,4,5,5] 有两个子阵列满足标准:[1,1,2,2]和[4,4,5,5,5]。最大长度子阵列有5个元素 PickingNumber具有以下参数:挑选数字-解决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
- 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您传入的参数上的代码>。末尾的code>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}