使用C#从输入列表中获取具有固定总和的随机数集

时间:2016-10-29 22:31:27

标签: c# algorithm list random sum

我正在寻找一个C#算法,它会从输入List给出一组随机整数,这样得到的随机整数之和就是N.

例如: 如果列表是{1,2,3,4,5,6 ... 100}且N是20,那么算法应该返回一组随机数,如{5,6,9}或{9,11}或{1,2,3,4,10}等。

请注意,结果集中的整数计数不需要修复。此外,输入列表可以具有重复的整数。性能是我的首要任务之一,因为输入列表可能很大(大约1000个整数),我需要在单个Web请求中随机化大约2-3次。如果列表存在性能问题,我很灵活,不会坚持使用List作为数据类型。

我尝试过以下方法,这种方法非常简陋且性能效率低下:

  1. 使用Random类从输入列表中获取随机索引
  2. 从#1中获得的索引处的输入列表中获取整数。让我们称之为整数X。
  3. Sum = Sum + X。
  4. 从输入列表中删除X,以便下次不会选中它。
  5. 如果Sum小于所需的总N,则将X添加到outputList并返回#1。
  6. 如果总和超过所需总数N,请重新初始化所有内容并重新启动该过程。
  7. 如果Sum等于所需的总N,则返回outputList

    while(!reachedTotal)
    {
        //Initialize everything
        inputList.AddRange(originalInputList);
        outputList = new List<int>();
        while (!reachedTotal)
        {
            random = r.Next(inputList.Count);
            sum += inputList.ElementAt(random);
            if(sum<N)
            {
    
                outputList.Add(inputList.ElementAt(random));
                inputList.RemoveAt(random);
            }
            else if(sum>N)
                break;
            else
                reachedTotal = true;
        }
    }
    

1 个答案:

答案 0 :(得分:0)

这是一种随机方法,可以在10%的N范围内提供解决方案 - 假设存在一个

using System;
using System.Collections.Generic;
using System.IO;
using System.Text;

namespace StackOverflowSnippets
{
    class Program
    {
        static void Main(string[] args)
        {
            // ----------------------------------------------------------------------------------
            // The code you are interested in starts below this line
            const Int32 N = 100;
            Int32 nLowerBound = (90 * N) / 100; Int32 nUpperBound = (110 * N) / 100;

            Random rnd = new Random();
            Int32 runningSum = 0;
            Int32 nextIndex = 0;

            List<Int32> inputList = GenerateRandomList( /* entries = */ 1000);
            List<Int32> o = new List<Int32>();

            while (runningSum < nLowerBound)
            {
                nextIndex = rnd.Next(inputList.Count); if (nUpperBound < (runningSum + inputList[nextIndex])) continue;

                runningSum += inputList[nextIndex];
                o.Add(inputList[nextIndex]);
                inputList.RemoveAt(nextIndex);
            }
            // The code you are interested in ends above this line
            // ----------------------------------------------------------------------------------

            StringBuilder b = new StringBuilder();

            for(Int32 i = 0; i < o.Count;i++)
            {
                if (b.Length != 0) b.Append(",");
                b.Append(o[i].ToString());
            }

            Console.WriteLine("Exact N    : " + N);
            Console.WriteLine("Upper Bound: " + nUpperBound);
            Console.WriteLine("Lower Bound: " + nLowerBound);
            Console.WriteLine();

            Console.WriteLine("sum(" + b.ToString() + ")=" + GetSum(o).ToString());
            Console.ReadLine();
        }

        // -------------------------------------------------------------------
        #region Helper methods
        private static object GetSum(List<int> o)
        {
            Int32 sum = 0;

            foreach (Int32 i in o) sum += i;

            return sum;
        }
        private static List<Int32> GenerateRandomList(Int32 entries)
        {
            List<Int32> l = new List<Int32>();

            for(Int32 i = 1; i < entries; i++)
            {
                l.Add(i);
            }

            return l;
        }
        #endregion
    }
}

修改

  1. 忘记从输入列表中删除元素,使其无法选择两次
  2. 修正了&#39;删除元素&#39;插入