查找奇数整数-Ruby嵌套循环错误

时间:2018-09-09 17:27:18

标签: ruby nested-loops

我在代码战中曾问过这个问题:“给一个数组,找到出现奇数次的int。总是只有一个整数出现奇数次。”

代码:

def find_it(seq)
  int = []
  for a in seq do
    count = 0
    for b in seq do
      if a == b
        count += 1
      end
    end
    if count % 2.0 != 0
      int << b
    end
  end      
  puts int.uniq[0].to_i
end

已针对几个输入对它进行了测试,但是对于这两个数组,答案是错误的:

find_it([1,1,2,-2,5,2,4,4,-1,-2,5])-返回5而不是-1

find_it([1,1,1,1,1,1,10,1,1,1,1])-返回1而不是10

我的代码出了什么问题?

5 个答案:

答案 0 :(得分:1)

if count % 2.0 != 0
      int << b
    end

这里的问题是将b而不是a推入整数数组,所以发生的是,推入b的最后一个值(即最后一个值)而不是推入计算的值尽管b和counter彼此无关,但只要计数器为奇数为条件,数组中的元素即可。为了解决这个问题,您可以将b替换为a,以便将您要测试的值与第二个循环中的其他元素进行比较

修复:

if count % 2.0 != 0
      int << a
    end

类似但更简单的代码可以完成类似的工作,只是以更短和更易于理解的方式是:

def find_it(seq)
  numberWithOddCount = 0
  seq.each do |currentElement|
    counter = 0
    seq.each { |elementToCompare| counter += 1 if currentElement == elementToCompare}
    numberWithOddCount = currentElement if counter % 2 != 0
  end
  numberWithOddCount
end

只需添加一些tid位,您还可以利用它们来缩短和简化代码。

快乐编码!

注意:

您可以以创造性的方式利用内置的ruby方法,使代码在几行(甚至一行)中完成您想要的操作,例如@iGian在问题注释中所做的操作,但是如果您还是不熟悉ruby,那么最好在学习它们时一一使用这些方法,否则您会感到困惑。但是,如果您愿意花时间现在学习它们,我建议您带走他的代码,并将每个方法的执行分成自己的一行,并输出每个方法的操作以了解正在做什么。并练习分别使用。

答案 1 :(得分:1)

def find_it(seq)
  seq.group_by{|x| x}.select{|k, v| (v.count % 2.0 !=0)}.first[0]
end

上面的代码将采用数组中的序列。在这里,我们按元素分组:

例如:

[1,1,2,-2,5,2,4,4,-1,-2,5].group_by{|x| x}
# => {1=>[1, 1], 2=>[2, 2], -2=>[-2, -2], 5=>[5, 5], 4=>[4, 4], -1=>[-1]}

获得以上结果后,我们发现其元素计数与选择条件不奇数。

例如:

[1,1,2,-2,5,2,4,4,-1,-2,5].group_by{|x| x}.select{|k, v| (v.count % 2.0 !=0)}

我们将得到的结果为{-1=>[-1]}

我们将键作为结果元素。

答案 2 :(得分:1)

@aimen_alt正确对待您的错误

但让我们分解一下问题。

首先,您需要计算每个数字的出现。 其次,您需要找到带有奇数个外观的一个。 根据问题,只有一个这样的数字,因此您可以立即将其退回。

通过扫描序列中序列中的每个项目,您可以按照O(N^2)的方式进行操作(因此,序列中的N个项目乘以序列{{1}的大小) } = N)。您可以通过构造一个N*N来线性地*,然后获得具有奇数值的键:

Hash

要更加习惯用法,您可以使用def find_it(seq) numbers = {} seq.each do |item| numbers[item] = numbers[item].to_i + 1 end numbers.select{ |k,v| v.odd? }.first.first end 对数字本身进行分组:

group_by

您会看到每个值都是一个Array,而您只需要获得一个包含奇数项的值:

seq = [1, 2, 6, 1, 2]
seq.group_by{ |item| item }
#=> {1=>[1, 1], 2=>[2, 2], 6=>[6]}

最后一件事是获取键的值:

seq = [1, 2, 6, 1, 2]
seq.group_by{ |item| item }.select{ |k, v| v.size.odd? }
#=> {6=>[6]}

所以,最终的解决方案是

seq.group_by{ |item| item }.select{ |k, v| v.size.odd? }.keys.first

@pascalbetz提到:

def find_it(seq)
  seq.group_by{ |item| item }
     .select{ |k, v| v.size.odd? }
     .keys
     .first
end

答案 3 :(得分:1)

这个怎么样

def find_it(seq)
  seq.reduce(:^)
end

^ -> 这个符号是按位XOR。 reduce 函数正在获取每个值并执行内部分配的任何工作。在这种情况下,它获取每个元素并执行 XOR 操作。第一个元素与零进行异或,下一个元素与前一个结果进行异或,依此类推。

就这样,我们找到了奇数元素。

异或运算的工作原理

0 ^ 2 = 2
4 ^ 4 = 0

如果您想了解更多关于异或的信息。请参阅this

答案 4 :(得分:0)

感谢您提供所有详细的答案,现在我将讨论每个人的答案。我是Ruby的新手,我仍在学习方法/使用它们的规则/ Big O表示法,因此,我非常感谢大家的投入。 Codewar列出了一些排名最高的解决方案。这似乎是迄今为止最快的:

def find_it(seq)   
   seq.detect { |n| seq.count(n).odd? } 
end