【问题标题】:How to make this function process in constant time?如何使这个函数在恒定时间内处理?
【发布时间】:2012-07-30 15:13:07
【问题描述】:

我需要找到这个无限级数的第 n 项:1,2,2,3,3,3,4,4,4,4...

你能给我这个任务的常数时间函数吗?

int i = 1;
while(true)
{
   if(i = n)
      //do things and exit the loop

   i++;
}

我认为这不会是一个常数时间函数...

【问题讨论】:

  • return x[n - 1]; 固定时间够你用吗?
  • 澄清一下,数组是否总是包含一个“1”、两个“2”、三个“3”等?
  • 哦,你想要第n个唯一词吗?
  • 我认为我们都在关注其中的“数组”部分,这不是他的问题。我认为问题是,“如何确定在 O(1) 时间内遵循这种模式的数字序列的第 n 项?”
  • 我不知道数组的长度或任何东西。我只知道数组的模式(例如:数组将有 1 个值为 1 的项目,2 个值为 2 的项目,3i 和 v 3,...,10 i 和 v 10)

标签: c# time-complexity


【解决方案1】:

编辑

在阅读了更多的 cmets 之后,我似乎误解了这个问题。

如果您想在一个 array 中以恒定时间在 nth 位置找到项目,那么答案很简单:x[n],因为数组访问是恒定时间。但是,如果由于某种原因您使用了一些访问时间不固定的容器(例如链表),或者不想在数组中查找值,则必须使用 arithmetic series 公式来找到答案.

算术级数告诉我们ith 唯一项的位置n 将是

n = i * (i - 1) / 2

所以我们只需要求解i。使用二次公式,并丢弃无意义的否定选项,我们得到:

i = Math.Floor( (1 + Math.Sqrt(1 + 8 * n)) / 2)

原始回复

我假设您正在寻找第 n 个 unique 项的 位置,否则问题就很简单了。

听起来第 n 个唯一术语的第一次出现应该跟在 arithmetic series 之后。 IE。第 n 个唯一项的位置是:

n * (n - 1) / 2

【讨论】:

  • +1 假设值始终遵循该模式,并且“术语”他的意思是值,那么是的,这很好用
  • 如果他想要给定系列的第 n 个唯一项,那么答案是 return n;...
  • 不,我想知道第 n 个索引处的值,而不知道孔数组,只知道数组的模式
  • @HansZ 只是因为数组从 1 开始。遵循从任意数字开始的相同模式会使问题变得更有趣
  • @ngmiceli return n + k - 1; //k is the starting number
【解决方案2】:

根据我对问题的理解,这更像是一道数学题,而不是编程题。

如果问题是:

给定一个由 1 的 1 份、2 的 2 份、3 的 3 份... n 份 n 组成的无限级数,这个级数的第 k 个值是多少? p>

现在处理这个问题的第一个线索是在第一次出现 n + 1 之前有 1 + 2 + 3... + n 个值。具体来说,在 n+ 之前有(前 n 个数字的总和)值1,或 (n)(n-1)/2。

现在设置 (n)(n-1)/2 = k。乘以并有理化为 n^2 - n - 2k = 0。使用二次方程求解,得到 n = (1 + sqrt(1+8k))/2。下限为您提供了 n 之前有多少完整副本,并且令人高兴的是,给定从零开始的索引,下限为您提供数组中第 k 个点的值。

这意味着你在 c# 中的最终答案是

return (int) Math.Floor((1 + Math.Sqrt(1 + 8 * k)) / 2);

鉴于非零索引,

return (int) Math.Floor((1 + Math.Sqrt(-7 + 8 * k)) / 2);

【讨论】:

    【解决方案3】:
            public static long Foo(long index)
            {
                if (index < 0)
                {
                    throw new IndexOutOfRangeException();
                }
    
                long nowNum = 0;
                long nowIndex = 0;
                do
                {
                    nowIndex += nowNum;
                    nowNum++;
                } while (nowIndex < index);
                return nowNum;
            }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2016-11-13
      • 2018-01-18
      • 1970-01-01
      • 2013-10-20
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多