给定一个包含整数的数组(长度至少为3,但也可以很大),该数组要么完全由奇数组成,要么完全由偶数组成,只有一个整数N。编写一个方法,将数组作为参数并返回这个离群值N。
这是我的代码,到目前为止,它似乎不工作:
arr = [160, 3, 1719, 19, 11, 13, -21]
n = arr.length
def getOddOccurrence(arr, arr_size)
for i in range(0, arr_size)
count = 0
for j in range(0, arr_size)
if arr[i] == arr[j]
count += 1
end
if(count % 2 != 0)
return arr[i]
end
end
end
return -1
end
print getOddOccurrence(arr, n)
字符串
我需要对这个代码做什么修改?
4条答案
按热度按时间llycmphe1#
这里有一个简单的方法
字符串
group_by(&:odd?)
将为奇数和偶数生成2个哈希值values
将获取哈希值。2个数组,用于偶数和奇数sort_by(&:count)
对数组排序,值少的数组优先[0][0]
获取第一个数组的第一个数字uidvcgyl2#
这里有一个很难理解(很难看)但相对简单的解决方案,它需要O(
arr.size
)时间和O(1)额外的存储空间,而且一旦找到异常值,它就会“短路”。基本思路是这样的:偶数的最低有效位为0,奇数的最低有效位为1,因此,如果对相邻的一对数字进行异或运算,则只有在它们缺少奇偶校验的情况下,最低有效位才会为1。在第一对数字发生异或运算后,第一次出现异或运算时,您已经找到了离群值。如果第一对数字发生了异或运算,则需要检查第二对数字。如果第二对数字的异或运算结果为0,第一个值是离群值,否则是第二个值。
字符串
这里有一个类似的概念,有点像Ruby:
型
如果您更喜欢查看2的子集,请对前3个值进行一次性检查,然后使用
cons(2)
子集。您也可以使用均匀性(或奇数)一致性检查来取代比特测试,以提高可读性:型
我终于有了几分钟的空闲时间来总结一个基准:
型
如您所见,我在偶数数组的末尾放置了一个奇数值,以最大化所需的搜索。
赢家是。
型
......萨加尔·潘迪亚的一句话!
基于
find
的方法明显优于each_cons
。使用Ruby的odd
/even
方法与二进制操作相比,似乎只有很小的影响。有趣的是,使用.each_cons(3)
而不是.each_cons(2)
的相对影响也很小,尽管两者都明显被萨加尔和Sergio的方法所主导。v2g6jxz63#
这里是一个线性时间常数记忆算法
字符串
dy1byipe4#
与其给予你一个解决方案,不如让我看看我是否能帮助你理解什么似乎是绊倒你的。我将忽略许多“Ruby主义”,它们可以缩短很多东西,因为它们很好,但最终似乎你仍然需要理解底层方法,而不是捷径,因为这是从长远来看帮助你更好地编程的东西。
字符串
上面的代码是在数组中寻找两个相等的数字。这意味着
count
永远不会增加,除非你的数组包含两个相同的值,这不是你想要的任务描述。此外,这个问题真的不需要你比较数组中的两个数字。你只需要确定每个数字是奇数还是偶数,并找到离群值。最简单的(也可能是最常见的)确定一个数是否为奇数的编程方法是使用模运算符(
%
)。你在检查你的count
变量时使用了这个,这也不是你真正需要的。相反,你应该对数组中的每个条目使用它。所以对于某个整数值n
,如果n % 2
是偶数,它将为0,如果它是奇数,它将为1。看起来你有点理解这一点,但是对数组中的每个数字使用它来确定它是偶数还是奇数,而不是count
变量,然后你可以对每个数字的信息进行操作。一旦你确定了数组中的每个数字是偶数还是奇数,你就需要一种方法来跟踪你是在搜索奇数还是偶数。最简单的方法是在一个变量中跟踪偶数/奇数计数,但是有一个变量用于偶数计数,另一个变量用于奇数计数。所以当你遇到偶数时,你可以在偶数计数上加1,奇数也是如此,但只限于奇数计数。这样你就知道你要找的类型了(偶数或奇数)是在你完成遍历数组后,计数等于1的值。这意味着这些变量应该在遍历数组的循环之外,因为你不希望它们为数组中的每个数字重置,你可能也会在循环之后看它们。
一旦你确定了你是在寻找奇数还是偶数,你可以第二次遍历数组(不是嵌套循环,而是在第一次循环之后的第二次循环),并根据需要从数组中返回奇数或偶数。有很多方法可以不需要第二次循环,但我试图让它直接前进。
希望这能帮助你想出自己的解决方案,这样你就可以从解决问题中学习。如果你让它与我的基本布局一起工作,有几种方法可以让它在性能或代码量方面更好(比如不使用第二个循环)。