使它更简单,以便更快

时间:2018-09-04 16:40:11

标签: ruby

我很新,在练习中遇到了问题。 我解决了这个问题,可以用,但是检查更多数字-最大长度aprox时太慢了。 = 1.000.000。 怎么写才能更快地解决?

<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<form action="target.php">
<table name="criteria_search" align="left" border="1" style="margin-right:70px">
<tr><td class="dataLabel"><strong>Add Rule : </strong>
  <select name="rule" id="rule" class="action"> 
   <optgroup label="Simple Rules">
    <option value="instructions" selected="selected">&nbsp;</option>
    <option value="email">Email</option>
    <option value="assigned">Assigned Racecourse</option>
   </optgroup>
  </select>
</td><td class="dataLabel" id="email" style="display:none">
  <b>email:</b>
  <br/><label><input type="radio" name="email_c" value="true_ex"> yes</label>
  <br/><label><input type="radio" name="email_c" value="false"> no</label>
  <br/><label><input type="radio" name="email_c" value="soon"> not yet</label>
 </td>
<td class="dataLabel" id="assigned" style="display:none">
  Racecourse<br/>
  <b>Assigned To: </b>
  <select name="selected_assigned_location">
   <option value=""></option>
   <option value="a">racecourse A</option>
   <option value="b">racecourse B</option>
   <option value="c">racecourse C</option>
  </select>
 </td>
</tr>
</table>
</form><br style="clear:both" />
<div id="show"></div>

测试:

def find_dups_miss(arr)
    ((arr.sort.first..arr.sort.last).to_a - arr.sort)  + [arr.select{|item| arr.count(item) > 1}.uniq.sort]
end

它需要找到丢失的数字和重复项。

错误消息: 为什么我的代码超时? 我们的服务器配置为仅允许一定时间来执行您的代码。在极少数情况下,服务器可能会承担过多的工作,并且根本无法有效地运行您的代码。尽管大多数情况下,此问题是由效率低下的算法引起的。如果您多次看到此错误,则应尝试进一步优化代码。

3 个答案:

答案 0 :(得分:3)

我们得到了一个整数数组arr,其属性是它包含min_valmax_val之间的每个整数,但其中一个为min_val, max_val = arr.minmax。我们希望确定丢失的整数以及arr中的重复值。

require 'set'

def missing_and_dups(arr)
  smallest, largest = arr.minmax
  dups = Set.new
  all = arr.each_with_object(Set.new) { |n,all| dups << n if all.add?(n).nil? }
  [(smallest+largest)*(largest-smallest+1)/2 - all.sum, dups.to_a]
end

missing_and_dups [10,9,8,9,6,1,2,4,3,2,5,5,3]
  #=> [7, [9, 2, 5, 3]]

请注意,如果要添加的元素已经在集合中,则Set#add?返回nil。而不是使用

找到丢失的元素n
((smallest..largest).to_a - arr).first

我利用了以下事实

all.sum + n = (smallest+largest)*(smallest+largest-1)/2

答案 1 :(得分:1)

这大约是我现在能解决这个问题的速度

def find_dups_miss(arr)
  groups = arr.group_by(&:itself) 
  arr.minmax.reduce(:upto).to_a - groups.keys << groups.select {|_,v| v.size > 1}.keys.sort
end

基于发布的Array

的说明

首先,我们将Array元素单独分组

{10=>[10], 9=>[9, 9], 8=>[8], 6=>[6], 1=>[1], 2=>[2, 2], 4=>[4], 3=>[3, 3], 5=>[5, 5]}

然后,我们根据Enumerator的最小和最大值(arr.minmax.reduce(:upto))创建一个Array,将其隐式覆盖到Arrayto_a)并从上一个分组中减去所有keys

arr.minmax.reduce(:upto).to_a - groups.keys
#=> [7]

然后,我们收集原始Array中多次出现的所有数字:(我对它们进行了排序是因为对期望的结果进行了排序)

groups.select {|_,v| v.size > 1}.keys.sort
#=> [2, 3, 5, 9]

并使用Array#<<将此Array推回到上一步中创建的

#=> [7,[2, 3, 5, 9]]

如果仅遗漏了一个数字,则以下内容会更快一些,因为它不会在第一个遗漏的数字上产生额外的Array和短路:

def find_dups_miss(arr)
  groups = arr.group_by(&:itself) 
  [groups.select {|_,v| v.size > 1}.keys.sort].unshift(arr.minmax.reduce(:upto).find {|n| groups[n].nil?} )
end

另外,对于非常大的Array

groups.collect {|k,v| k if v.size > 1 }.compact.sort 

似乎比

更有效率
groups.select {|_,v| v.size > 1}.keys.sort

答案 2 :(得分:0)

我同意最好将其放在代码审查中,但是要回答您的问题,可以使用更好的数据结构来解决此问题,请考虑将其用作哈希:

def find_dups_missing(arr)
  min, max = arr.min, arr.max
  hash = {}
  min.upto(max) { |i| hash[i] = :sentinel }
  arr.each { |el| hash[el] == :sentinel ? hash[el] = 1 : hash[el] += 1 }

  hash.select { |_, v| v == :sentinel }.keys << hash.select { |_, v| v != :sentinel && v > 1 }.keys
end

我们循环遍历,构建一个哈希,其中每个键是一个从minmax的数字,并且该值指向一个只是占位符的对象(我称之为sentinel) 。

接下来,我们遍历数组,询问哈希值是否仍在其占位符位置,如果是,则将值设置为1,但如果不是,则仅递增。这样,我们就可以跟踪何时第一次看到某个值以及随后的几次(即重复)。

然后,在全部说完之后,我们得到一个如下所示的哈希:

{1=>1, 2=>2, 3=>2, 4=>1, 5=>2, 6=>1, 7=>:sentinel, 8=>1, 9=>2, 10=>1}

我们知道值> 1在哪里,我们有重复项,我们还知道值仍在sentinel哪里,我们从未在数组中看到它,这是我们的差距。

总的来说,此方法在O(n)个空间中平均O(n)个时间运行。