我有一个带整数n的函数并返回一个字符串,其中包含从1到n的数字,用','分隔。现在这个数字整数n可以是任何数字,大到10亿。什么是最好的解决方案。我如何管理内存相关的问题,如果RAM只有2 Gb,那么如果我在C#中返回这个大字符串会发生什么。功能签名是:
string convtostr (int n)
{}
所以输入例如可能是n = 5,然后输出将是这样的字符串 “1,2,3,4,5”
答案 0 :(得分:2)
您无法在.NET中创建如此大的字符串。无论你有多少内存,2GB都是对象的最大大小。
您可以提供一个对象,它允许您迭代结果中的字符,但只能按需计算它们,而不是返回字符串。
答案 1 :(得分:2)
我想最好的解决方案就是不要使用这个字符串:)你可以将这个字符串包装在一个只包含数字n的类中:
class LargeStringWithNumbers
{
int upper_bound;
public void Print()
{
for (int j = 0; j < upper_bound; j++ )
{
System.Console.Write("{0};", j);
}
System.Console.Write("\n");
}
}
它的行为与您始终包含字符串的行为完全相同,除非您不这样做。
答案 2 :(得分:0)
如果您的方法足迹必须与您显示的足迹完全匹配,则无法完成。因为您无法继承String
并创建一个适用于&gt; 2GB的新更好的类型
如果您对n
的最大输入值的假设不正确,那么您可以提供匹配足迹的工作解决方案。例如n
的最大值是10000
还是非常小。
但是我认为@MikeSamuel建议的IEnumerable<char>
方法是唯一能够提供接近所述要求的工作解决方案的答案。
正如您标记了此c# 4.0
他们很可能正在寻找使用yield
语法的解决方案,例如:
static IEnumerable convtostr(int n)
{
for (int i = 1; i < n; i++)
yield return string.Format("{0}, ", i.ToString());
yield return n.ToString();
}
然后您可以解释您使用它,如下所示
int input = 1000000000; // 1 billion.
foreach (var value in convtostr(input))
{
Console.Write(value );
}
这很可能是他们想要你回答的。由于实际上不会将整个最终字符串存储在内存中,因此这将适用于非常少的活动RAM。
编辑:与@suddnely_me建议类似的另一个答案是为每个号码传递一个操作,例如:
static void convtostr(int n, Action<int> action)
{
for (int i = 1; i <= n; i++)
action(i);
}
然后使用:
调用它int input = 1000000000; // 1 billion.
convtostr(input, n =>
{
if (n < input) { Console.Write("{0}, ", n); }
else { Console.Write(n); }
});
实际上与使用yield
语法几乎相同。
答案 3 :(得分:0)
让我们看看设计限制:
n = 10亿:
当n为10亿时,则逗号“,”单独占用您的可用空间,因为char === 2个字节;这样2个字节* 10亿= 2 GB - 2个字节(实际上你有20亿个 - 1个逗号)。因此,从这个基本观察来看,想法必须是将结果压缩到2GB。 String是一个对象,大小限制为2GB。
因此,问题是如何在对象之间编码消息?即,一个对象将使用n调用该函数,并期望来自被调用对象的消息。请注意,您没有被要求打印结果,而是返回一个字符串。如果你提出的功能签名实际上是面试官在董事会上所写的内容(而不是你对问题的解释),那么来自suddnly_me的答案就不行了,否则就是你的答案。
假设签名是面试官写的,那么如何在两个对象之间发送压缩消息呢?虽然听起来很滑稽,但我会把n作为字符串返回。
string convtostr (int n)
{
return n+"";
}
然后根据返回值的用途,我会编写解码器/解析器来解码消息。例如,如果调用需要将字符串写入文件,则编写器方法/函数会将字符串转换回int,并在写入文件时从1到n进行迭代。
我已经走了很长时间。你明白了。