程序输入一个双精度列表,输出需要是一个字符串,其中包含按值分组的列表值。如果列表值相等,则将对它们进行分组。 就像是: 输入9,77,5,5,31 =>输出9 77 2 * 5 31
我在C#中创建了一个算法(在Java中我认为几乎是相同的),但我不确定它是否可以改进其速度或代码质量,或者它是否有一些我看不到的错误。该算法还有一些输入,输出示例如下。
{{1}}
如果您发现了一些错误或看到可以做的一些改进,请告诉我。
此外,如果你知道这个要求的另一个实现,请添加它,以便可以完成算法之间的结果,速度,代码质量的比较......并找到处理这个问题的最佳方法。
答案 0 :(得分:3)
由于要求只对连续相等的值进行分组,因此另一个答案中提到的Dictionary
和LINQ GroupBy
方法不适用,因为它们会产生不正确的输入结果序列如1,2,1
。此外,没有标准的LINQ方法可以进行此类分组(最终Aggregate
方法除外),但它只不过是低效的for
/ foreach
循环等效方法。
很快,您的算法最适合此类任务。但实施不是。
主要的瓶颈是Peroxy提到的字符串连接,使用StringBuilder
类可以很容易地修复(在另一个答案中也提到)。一旦你这样做,性能将会很好。
我在实现中看到的另一个问题是使用特殊值(double.MinValue
),重复的角落案例检查,在体内减少for
循环变量等等。所以虽然它可能有用但我不喜欢直接看到一个错误,很难遵循算法逻辑并发现潜在的错误只是阅读实现。算法本身很简单,我会这样实现:
static string ListAsString(List<double> input)
{
var sb = new StringBuilder();
for (int i = 0; i < input.Count; )
{
var value = input[i];
int count = 1;
while (++i < input.Count && input[i] == value)
count++;
if (sb.Length > 0) sb.Append(' ');
if (count > 1) sb.Append(count).Append('*');
sb.Append(value);
}
return sb.ToString();
}
哪个IMO更容易理解。请注意,没有重复的代码,没有特殊值,循环变量i
前进仅在外部循环体内的一个位置完成。同样,这与性能无关(由StringBuilder
用法提供),但只是可读性,冗余消除和不易出错。
答案 1 :(得分:2)
就个人而言,我认为这里有Dictionary
使用的巨大潜力,这是我用字典实现的快速解决方案:
var input = new List<double> { 9, 77, 5, 5, 31 };
var dict = new Dictionary<double, int>();
var listAsString = new StringBuilder();
foreach (var item in input)
{
if (dict.ContainsKey(item))
dict[item]++;
else
dict[item] = 1;
}
foreach (var item in dict)
{
listAsString.Append(item.Value > 1 ? $"{item.Value}*{item.Key} " : $"{item.Key} ");
}
Console.WriteLine(listAsString);
如果您想要一种无效的LINQ单线解决方案:
string result = string.Join(" ", input.GroupBy(i => i)
.Select(x =>
x.Count() > 1 ?
$"{x.Count()}*{x.Key} " :
$"{x.Key} "));
但是,我相信你的方法编写得很好,虽然比字典的方法稍差,但你的解决方案的主要缺点是你在构建最终字符串时使用字符串,你绝对应该使用{ {1}},我在您的方法中引入了StringBuilder
并对这三种方法进行了比较:
StringBuilder
您的解决方案始终是最快的,如果您想加快速度,保留解决方案,但将其更改为使用Dictionary | Your method | GroupBy method
------------------------------------------------
2 ms | 0 ms | 5 ms n=3
0 ms | 0 ms | 0 ms n=6
0 ms | 0 ms | 0 ms n=12
0 ms | 0 ms | 0 ms n=24
0 ms | 0 ms | 0 ms n=48
0 ms | 0 ms | 0 ms n=96
0 ms | 0 ms | 0 ms n=192
0 ms | 0 ms | 0 ms n=384
0 ms | 0 ms | 0 ms n=768
0 ms | 0 ms | 0 ms n=1536
1 ms | 0 ms | 1 ms n=3072
3 ms | 2 ms | 3 ms n=6144
5 ms | 4 ms | 6 ms n=12288
8 ms | 7 ms | 14 ms n=24576
14 ms | 13 ms | 25 ms n=49152
31 ms | 32 ms | 66 ms n=98304
80 ms | 59 ms | 146 ms n=196608
149 ms | 123 ms | 294 ms n=393216
246 ms | 218 ms | 504 ms n=786432
483 ms | 428 ms | 1040 ms n=1572864
999 ms | 873 ms | 2070 ms n=3145728
1995 ms | 1784 ms | 3950 ms n=6291456
,请使用StringBuilder
代替listAsString.Append(currentElem + " ")
。
listAsString += currentElem + " "
的集合进行操作,则可以使用 GroupBy
,如果您希望使用可读性超过速度,请使用n < 1000
解决方案。