【问题标题】:Return number from a collection in a non-sequential, not random and non-repeating way以非顺序、非随机和非重复的方式从集合中返回数字
【发布时间】:2020-05-17 10:14:40
【问题描述】:

我有一个很大的整数序列 (1M+)。

每当用户查询我的 API 时,我都需要以非顺序、非随机和非重复的方式选择其中一个整数。我无法存储之前返回的所有整数的历史记录。

我想出了一个“摇动”算法,它只是在一个非常大的数组中移动值:

            static int[] Shake(
                int[] values,
                Func<int, bool> predicate,
                Func<int, int> moveBy)
            {
                static int Adjust(int index, int size)
                {
                    while (index > size - 1) index -= size;
                    while (index < 0) index += size;
                    return index;
                }

                var count = values.Length;
                for (var oldIndex = 0; oldIndex < count - 1; oldIndex++)
                {
                    if (!predicate(oldIndex)) continue;

                    var newIndex = Adjust(oldIndex + moveBy(oldIndex), count);

                    var value = values[oldIndex];
                    values[oldIndex] = values[newIndex];
                    values[newIndex] = value;
                }

                return values;
            }

            var indexes = Enumerable.Range(0, size).ToArray();

            indexes = Shake(indexes, idx => idx % 3 == 0, idx => idx + 50);
            indexes = Shake(indexes, idx => idx % 2 == 0, idx => 12);

            return indexes;

此算法有效,但效率不高:

  1. 我需要创建并循环遍历大量项目
  2. 可能会消耗大量内存/CPU
  3. 这是一个相当慢的算法

我想知道是否有另一种方法可以在 非顺序、非随机和非重复方式(可能是公式/数学系列,但我的数学很烂)。

感谢您的帮助

【问题讨论】:

  • “非顺序,非随机”对您意味着什么?您给出的示例似乎相当随机(尽管是一种非常可预测的随机性)。为什么Random.Next不够好?

标签: c# .net collections


【解决方案1】:

这里你有一个高效简单的解决方案,你只需要一个质数并记住n,下次你需要增加n。

class Program
{

    const long prime = 15_485_863;

    static void Main(string[] args)
    {
        const int  arrayLenght = 1_000_0000;

        var numbers = new int[arrayLenght];

        for (int i = 0; i < numbers.Length; i++)
        {
            numbers[i] = i;
        }

        var hashSet = new HashSet<int>();
        for (int i = 0; i < numbers.Length; i++)
        {
            var number = GetNonSequentialNotRandomNonRepeatingNumber(numbers, i);
            if (hashSet.Add(number) == false)
            {
                Console.WriteLine($"Something went wrong. {number} is duplicated");
            }
        }
    }

    static int GetNonSequentialNotRandomNonRepeatingNumber(int[] numbers, int n)
    {
        int pos = (int) ((prime * (long) n) % numbers.Length);
        return numbers[pos];
    }
}

【讨论】:

    猜你喜欢
    • 2013-05-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-01-20
    • 2013-12-24
    相关资源
    最近更新 更多