一种检查 num1 的数字是否是 num2 中的数字而不检查每个数字的方法?
假设我猜到了彩票号码:
1689
而彩票的运作方式是,数字的顺序并不重要,只要数字与实际中奖彩票号码中的数字1:1匹配即可。
因此,数字 1689 将是一个中奖彩票号码:
1896、1698、9816 等。
只要您猜测的每一位数字都出现在目标号码中,那么您就中奖了。
有什么数学方法可以做到这一点吗?
我通过 O(N^2) 循环检查每个数字与中奖彩票号码的每个数字(用模数将它们分开)解决了这个问题。 这很好,它有效,但我想知道是否有任何巧妙的数学技巧我可以做。
例如,一开始......我认为我可能会很棘手,只需取两个数字中每个数字的总和和乘积,如果它们匹配,那么你就赢了。
^ 你认为这可行吗?
但是,当我发现彩票猜测时,我很快就反驳了这一点:222 和 124 的数字不同,但乘积和和相同。
任何人都知道我可以使用的任何数学技巧来快速确定中的数字是否相同num1 与 num2 中的数字匹配,无论顺序如何?
Lets say I have guessed a lottery number of:
1689
And the way the lottery works is, the order of the digits don't matter as long as the digits match up 1:1 with the digits in the actual winning lottery number.
So, the number 1689 would be a winning lottery number with:
1896, 1698, 9816, etc..
As long as each digit in your guess was present in the target number, then you win the lottery.
Is there a mathematical way I can do this?
I've solved this problem with a O(N^2) looping checking each digit against each digit of the winning lottery number (separating them with modulus). Which is fine, it works but I want to know if there are any neat math tricks I can do.
For example, at first... I thought I could be tricky and just take the sum and product of each digit in both numbers and if they matched then you won.
^ Do you think that would work?
However, I quickly disproved this when I found that lottery guess: 222, and 124 have the different digits but the same product and sum.
Anyone know any math tricks I can use to quickly determine if the digits in num1 match the digits in num2 regardless of order?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(14)
一个可爱的解决方案是使用 Zobrist 哈希 的变体。 (是的,我知道这有点矫枉过正,而且是概率性的,但是嘿,它很“聪明”。)
将一个十元素数组
a[0..9]
初始化为随机整数。 然后,对于每个数字d[]
,计算a[d[i]]
的总和。 如果数字包含相同的数字,则结果相等; 概率很高(大约有多少个可能的整数),反之亦然。(如果你知道总共最多有 10 位数字,那么你可以使用固定数字 1, 10, 100, ... 而不是随机数来保证成功。这就是没有太多伪装的桶排序。 )
One cute solution is to use a variant of Zobrist hashing. (Yes, I know it's overkill, as well as probabilistic, but hey, it's "clever".)
Initialize a ten-element array
a[0..9]
to random integers. Then, for each numberd[]
, compute the sum ofa[d[i]]
. If the numbers contained the same digits, the resulting numbers will be equal; with high probability (~ 1 in how many possible ints there are), the opposite is true as well.(If you know that there will be at most 10 digits total, then you can use the fixed numbers 1, 10, 100, ... instead of random numbers for guaranteed success. This is bucket sorting in not-too-much disguise.)
如果 N 可以变得很大,那么对数字进行排序就是答案。
因为数字是 0..9,所以您可以计算数组 [0..9] 中彩票答案的每个数字出现的次数。
为了进行比较,您可以为猜测中遇到的每个数字减去 1。 当你遇到计数已经为 0 的数字时,你就知道猜测是不同的。 当你猜完所有数字时,猜测的数字是相同的(只要猜测的数字与彩票答案的数字一样多)。
If N can become large, sorting the digits is the answer.
Because digits are 0..9 you can count the number of occurrences of each digit of the lottery answer in an array [0..9].
To compare you can subtract 1 for each digit you encounter in the guess. When you encounter a digit where the count is already 0, you know the guess is different. When you get through all the digits, the guess is the same (as long as the guess has as many digits as the lottery answer).
对于每个数字 d 乘以第 (d+1) 个素数。
这比排序或桶方法更数学化,但效率较低。 其实就是变相的桶法。
For each digit d multiply with the (d+1)-th prime number.
This is more mathematical but less efficient than the sorting or bucket methods. Actually it is the bucket method in disguise.
我会对两个数字的数字进行排序并进行比较。
I'd sort both number's digits and compare them.
如果您只处理 4 位数字,我认为您不必过多考虑使用哪种算法。 它们的表现大致相同。
而且 222 和 124 的和也不相同
If you are only dealing with 4 digits I dont think you have to put much thought into which algorithm you use. They will all perform roughly the same.
Also 222 and 124 dont have the same sum
你必须考虑到,当 n 很小时,效率的顺序无关紧要,并且常数开始变得更重要。 你的数字实际上能达到多大? 你能得到最多10位数字吗? 20? 100? 如果你的数字只有几位数字,n^2 确实还不错。 如果您有数千位数字的字符串,那么您实际上可能需要做一些更聪明的事情,例如排序或存储桶。 (即计算 0、计算 1 等)
You have to consider that when n is small, the order of efficiency is irrelevant, and the constants start to matter more. How big can your numbers actually get? Can you get up to 10 digits? 20? 100? If your numbers have just a few digits, n^2 really isn't that bad. If you have strings of thousands of digits, then you might actually need to do something more clever like sorting or bucketing. (i.e. count the 0s, count the 1s, etc.)
我从 Yuliy 那里偷了答案,starblue(给他们投票)
除了 O(1)
排序之外,分桶是最快的 排序是 O(nlog2n)
Bucketsort 是一种 O(n) 算法。
因此,您需要做的就是执行两次(一次针对您的数字,一次针对目标集),如果数字相加,则它们匹配。
任何类型的排序都会增加开销,在这种情况下是不必要的。
我承认这不是最漂亮的代码。
I'm stealing the answer from Yuliy, and starblue (upvote them)
Bucketing is the fastest aside from the O(1)
Sorting is O(nlog2n)
Bucketsort is an O(n) algorithm.
So all you need to do is do it twice (once for your numbers, once for the target-set), and if the numbers of the digits add up, then they match.
Any kind of sorting is an added overhead that is unnecessary in this case.
Not the prettiest code, I'll admit.
创建一个包含 10 个下标为 [0 .. 9] 的整数的数组。
将每个元素初始化为不同的素数
将乘积设置为 1。
使用数字中的每个数字作为数组的下标,
取出质数,然后乘以它的乘积。
这为您提供了与数字顺序无关的独特表示。
对其他号码执行相同的过程。
如果唯一的表示匹配,则原始数字匹配。
Create an array of 10 integers subscripted [0 .. 9].
Initialize each element to a different prime number
Set product to 1.
Use each digit from the number, to subscript into the array,
pull out the prime number, and multiply the product by it.
That gives you a unique representation which is digit order independent.
Do the same procedure for the other number.
If the unique representations match, then the original numbers match.
如果不允许重复数字(但不确定是否是这种情况),则使用 10 位二进制数。 最高有效位代表数字 9,LSB 代表数字 0。依次处理每个数字,并翻转找到的每个数字的相应位。
因此 1689 将是:1101000010,9816
也将是:1101000010,
然后进行 XOR 或如果你是赢家,则减法将留下 0
这只是分桶的简单形式
If there are no repeating digits allowed (not sure if this is the case though) then use a 10-bit binary number. The most significant bit represents the digit 9 and the LSB represents the digit 0. Work through each number in turn and flip the appropriate bit for each digit that you find
So 1689 would be: 1101000010
and 9816 would also be: 1101000010
then a XOR or a subtract will leave 0 if you are a winner
This is just a simple form of bucketing
只是为了好玩,并以正常的方式思考,而不是排序和其他方式,而是进行删除操作。 如果结果字符串为空,则您获胜!
这也适用于重复数字。
Just for fun, and thinking outside of the normal, instead of sorting and other ways, do the deletion-thing. If resultstring is empty, you have a winner!
This works with repeating numbers too..
在存储数字之前对数字进行排序。 在那之后,你们的数字将相等。
Sort digits before storing a number. After that, your numbers will be equal.
遍历每个数字,并计算每个数字出现的次数(放入两个不同的 10 元素数组)怎么样? 完成总计后,比较每个数字的计数。 由于您只查看每个数字一次,因此时间复杂度为 O(N)。
代码看起来像这样:
上面的代码假设guessDigits和actualDigits都是char字符串; 如果它们包含实际数字,那么您可以跳过
- '0'
业务。可能有一些优化可以减少占用空间或更快终止,但这是 O(N) 方法的一个非常简单的示例。
顺便说一句,正如我在评论中提到的,由于零,乘法/求和比较肯定不起作用。 考虑 0123 和 0222。两种情况下乘积均为 0,总和均为 6。
How about going through each number, and counting up the number of appearances of each digit (into two different 10 element arrays)? After you'd done the totaling, compare the counts of each digit. Since you only look at each digit once, that's O(N).
Code would look something like:
Above code makes the assumption that guessDigits and actualDigits are both char strings; if they held the actual digits then you can just skip the
- '0'
business.There are probably optimizations that would make this take less space or terminate sooner, but it's a pretty straightforward example of an O(N) approach.
By the way, as I mentioned in a comment, the multiplication/sum comparison will definitely not work because of zeros. Consider 0123 and 0222. Product is 0, sum is 6 in both cases.
拆分为数组、排序数组、连接为字符串、比较字符串。
(我知道这不是数学技巧)
Split into array, sort array, join into string, compare strings.
(Not a math trick, I know)
您可以将数字放入数组中,对数组进行排序,然后逐个元素进行比较。 这将为您提供 O( NlogN ) 复杂度,这比 O( N^2 ) 更好。
You can place the digits into an array, sort the array, then compare the arrays element by element. This will give you O( NlogN ) complexity which is better than O( N^2 ).