Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/265.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 检测连续整数并折叠为字符串_C#_List_Algorithm - Fatal编程技术网

C# 检测连续整数并折叠为字符串

C# 检测连续整数并折叠为字符串,c#,list,algorithm,C#,List,Algorithm,免责声明:这是关于C 我有一个包含整数的枚举,例如: [1, 2, 3, 4, 7, 8, 10, 11, 12, 13, 14] 我想获得一个字符串,其中列出了连续整数的范围: 1-4, 7-8, 10-14 我想到了: public static void Main() { System.Diagnostics.Debug.WriteLine(FindConsecutiveNumbers(new int[] { 1,2, 7,8,9, 12, 15, 20,21 })); }

免责声明:这是关于C

我有一个包含整数的枚举,例如:

[1, 2, 3, 4, 7, 8, 10, 11, 12, 13, 14]
我想获得一个字符串,其中列出了连续整数的范围:

1-4, 7-8, 10-14
我想到了:

public static void Main()
{
    System.Diagnostics.Debug.WriteLine(FindConsecutiveNumbers(new int[] { 1,2, 7,8,9, 12, 15, 20,21 }));
}

private static string FindConsecutiveNumbers(IEnumerable<int> numbers)
{
    var sb = new StringBuilder();
    int? start = null;
    int? lastNumber = null;
    const string s = ", ";
    const string c = "-";

    var numbersPlusIntMax = numbers.ToList();
    numbersPlusIntMax.Add(int.MaxValue);
    foreach (var number in numbersPlusIntMax)
    {
        var isConsecutive = lastNumber != null && lastNumber + 1 == number;
        if (!isConsecutive)
        {
            if (start != null)
            {
                if (sb.Length > 0) { sb.Append(s); }
                if (start == lastNumber)
                {
                    sb.Append(start); ;
                }
                else
                {
                    sb.Append(start + c + lastNumber); ;
                }
            }

            start = number;
        }
                
        lastNumber = number;
    }

    return sb.ToString();
}
该算法适用于有序输入。是否有一种内置的/LINQ/C更短的方法来实现这一点?

我建议分解:让我们将初始例程拆分为逻辑:


如果我们可以获得列表中的数字而不是枚举,那么我们就不需要访问所有的数字。前面的答案是时间复杂度为On,其中n是数组的大小。然而,如果我们有一个列表,这个问题可以在Oklogn中解决,其中k是组的数量


基本上,您可以使用稍加修改的二进制搜索来查找一个组的端点,这可以在Ologn中完成,然后从end+1开始,您可以对下一个组执行相同的操作。

很好的解决方案+1.选择g=>g.First.value==g.Last.value${g.First.value}:${g.First.value}-{g.Last.value}为了坚持要求的格式,很好地使用了!二进制搜索。这也是个好主意。但如果我正确理解了这个方法,那么只有在团队数量少的情况下,这才会证明它的优势。没错。如果期望每个组都有很少的元素,这意味着有很多组,那么使用这种方法是没有意义的。@JackMiller,我们也可以修改二进制搜索,在最坏的情况下,它将打开,而不是在k=n的情况下打开。因此,复杂性将优于Oklogn和On。
private static IEnumerable<(int left, int right)> Consecutive(IEnumerable<int> numbers) {
  int start = -1;
  int stop = -2;  

  foreach (var item in numbers) // numbers.OrderBy(x => x) to sort numbers
    if (item == stop + 1)
      stop = item;
    else {
      if (stop >= start)
        yield return (start, stop);

      start = item;
      stop = item;
    }  

  if (stop >= start)
    yield return (start, stop);  
}
private static string FindConsecutiveNumbers(IEnumerable<int> numbers) =>
  string.Join(", ", Consecutive(numbers)
    .Select(item => item.left == item.right 
       ? $"{item.left}" 
       : $"{item.left}-{item.right}"));
public static void Main()
{
    // 1-2, 7-9, 12, 15, 20-21
    System.Diagnostics.Debug.WriteLine(FindConsecutiveNumbers(new int[] { 
      1, 2, 
      7, 8, 9, 
      12, 
      15, 
      20, 21 }
    ));
}
int[] numbers = { 1, 2, 3, 4, 7, 8, 10, 11, 12, 13, 14 };

return string.Join(", ",
    numbers
        .Select((n, i) => new { value = n, group = n - i })
        .GroupBy(o => o.group)
        .Select(g => g.First().value + "-" + g.Last().value)
);