将 1,2,3,4,5,6,8,10,11 显示为 1-6,8,10-11
Posted
技术标签:
【中文标题】将 1,2,3,4,5,6,8,10,11 显示为 1-6,8,10-11【英文标题】:Display 1,2,3,4,5,6,8,10,11 as 1-6,8,10-11 【发布时间】:2013-02-03 20:36:20 【问题描述】:我有这个序列1,2,3,4,5,6,8,10,11
预期输出为 1-6,8,10-11
这个问题是关于以易于阅读的形式格式化序列
我尝试使用 c# 并使用了很多 if & else。
面试官说,有一些简单的算法可以做到这一点。
我不知道如何实现这个非常简单。
对于 1,2,3 我也显示了 1-3。他们说错了!。
此逻辑中是否涉及任何设计模式(解释器)?
【问题讨论】:
他们有没有说为什么从1,2,3
转换为1-3
是错误的?我看不出这个案子有什么问题
java display input in range 的可能重复项
是的,我只是想知道1-3
是否错误,因为您应该输出1-4
,或者它是否错误,因为他们只想替换一行中的 4+ 个元素,不是连续 3 个元素。
我喜欢这个问题有九个代码答案,而没有解释的答案。 (是的,这是一个非常简单的算法;但仍然如此。)
@KonradRudolph:如果您认为有必要,您可以随意添加。
【参考方案1】:
这是一种方法:
int[] numbers = 1, 2, 3, 4, 5, 6, 8, 10, 11 ;
int start, end;
for (int i = 0; i < numbers.Length; i++)
start = numbers[i];
while (i < numbers.Length - 1 && numbers[i] + 1 == numbers[i + 1])
i++;
end = numbers[i];
if(start == end)
Console.WriteLine(start);
else
Console.WriteLine(start + " - " + end);
这将显示随着范围递增的后续数字。不是线性增加的数字不会写成范围的一部分。
这是第一种方法的另一个版本,它利用相同的for
循环来迭代范围:
int temp = numbers[0], start, end;
for (int i = 0; i < numbers.Length; i++)
start = temp;
if (i < numbers.Length - 1 )
// if subsequent numbers are incremental loop further
if (numbers[i] + 1 == numbers[i + 1])
continue;
// if they are not, number at index i + 1 is a new 'start' for the next iteration
else
temp = numbers[i + 1];
end = numbers[i];
if (start == end)
Console.WriteLine(start);
else
Console.WriteLine(start + " - " + end);
【讨论】:
这个逻辑对我来说似乎很简单:) 我同意,逻辑和实现都很简单:) @IvanG 可以反过来吗?如果用户输入为 10,1-4,5-8, 9,则输出应为 1,2,3,4,5,6,7,8,9,10【参考方案2】:C# 中的一个简单实现可能如下所示:
public string Format(IEnumerable<int> input)
var result = string.Empty;
var previous = -1;
var start = -1;
var first = true;
foreach(var i in input)
if(start == -1)
start = i;
else if(previous + 1 != i)
result += FormatRange(start, previous, first);
first = false;
start = i;
previous = i;
if(start != -1)
result += FormatRange(start, previous, first);
return result;
public string FormatRange(int start, int end, bool isFirst)
var result = string.Empty;
if(!isFirst)
result += ", ";
if(start == end)
result += start;
else
result += string.Format("0-1", start, end);
return result;
这也将为输入1,2,3
输出1-3
,这是完全有效的。如果没有说明输出应该是什么,则无法回答该部分。
【讨论】:
很好的答案,但我认为重点(至少作为面试问题)是找到一个简单的算法,而不是通过使用 API 来“作弊”。 @Dukeling:识别范围是使用简单算法完成的。 @Dukeling:但我还是将其更改为不使用 LINQ 进行输出。【参考方案3】:可能不是面试问题的合适答案,但使用 LINQ 是解决此问题的另一种方法。
int[] numbers = 1, 2, 3, 4, 5, 6, 8, 10, 11 ;
var remains = numbers.AsEnumerable();
while (remains.Any())
int first = remains.First();
int last = remains.TakeWhile((x, i) => x - first == i).Last();
remains = remains.Skip(last - first + 1);
Console.Write(first + (first == last ? "" : "-" + last) + (remains.Any() ? "," : Environment.NewLine));
【讨论】:
这是这里最简洁的版本。 请注意,这是在迭代源序列 很多 次,这不适用于任意可枚举,即使它适用于数组。【参考方案4】:以下分组连续整数,并为每个组输出一个字符串。但是,它还允许您指定要连字的组的最小长度;少一点只会给你个人数字。因此,如果您只想连接 4 个或更多的组,则可以传入 4;如果你想用连字符对,你可以传入 2。(我自己也想用 3,但我不知道他们想要什么。)
它也不会保留任何数字集合,因为您不需要。
方法:
static IEnumerable<string> Group(IEnumerable<int> input, int minLength)
int currentStart = int.MinValue;
int currentLength = 0;
foreach (int c in input)
if (currentLength > 0)
if (currentStart + currentLength == c)
currentLength++;
else
if (currentLength >= minLength)
yield return string.Format("0-1",
currentStart, currentStart + currentLength - 1);
else
for (int i = currentStart; i < currentStart + currentLength; i++)
yield return i.ToString();
currentStart = c;
currentLength = 1;
else
currentStart = c;
currentLength = 1;
if (currentLength >= minLength)
yield return string.Format("0-1",
currentStart, currentStart + currentLength + 1);
else
for (int i = currentStart; i < currentStart + currentLength; i++)
yield return i.ToString();
用法:
int minCount = 3;
int[] input = new[] 1, 2, 3, 4, 5, 6, 8, 10, 11 ;
Console.WriteLine(String.Join(",", Group(input, minCount)));
【讨论】:
【参考方案5】:Java 代码:
int[] arr = 1,2,3,4,5,6,8,10,11;
int start = arr[0], last = arr[0];
String output = "";
for (int i = 1; i <= arr.length; i++)
if (i == arr.length || arr[i] != last+1)
if (output.length() != 0)
output += ",";
if (start == last)
output += start;
else
output += start + "-" + last;
if (i != arr.length)
start = last = arr[i];
else
last = arr[i];
System.out.println(output);
【讨论】:
【参考方案6】:这是我最好的尝试。不聪明,但足够简单,足以满足我相信的要求。我仍然很困惑为什么“1-3”是错误的......
var numbers = new int[] 1, 2, 3, 4, 5, 6, 8, 10, 11, 12 ;
var groups = new Dictionary<int, int>();
groups.Add(numbers.First(), numbers.First());
foreach (var num in numbers.Skip(1))
var grp = groups.Last();
if (grp.Value + 1 == num)
groups[grp.Key] = num;
else
groups.Add(num, num);
var output = string.Join(",", groups.Select(grp => (grp.Key == grp.Value) ? grp.Value.ToString() : grp.Key.ToString() + "-" + grp.Value.ToString()));
注意:当然,使用字典和 linq 等是完全没有必要的(对于需要算法的答案来说太具体了),但我认为它很好地突出了问题的分组方面
【讨论】:
【参考方案7】:这不是有效的 C# 代码,只是为了展示想法。
从 Min 到 Max 对列表进行排序,然后执行以下操作:
For i = Min to Max
if i < MaxFound
continue;
int step = 1;
Output = i;
while Found(i + Step)
Step++;
MaxFound = i + Step;
if i < MaxFound
Output = (i + "-" + MaxFound);
Output += ", ";
【讨论】:
【参考方案8】:这是一种方法:
public static void main(String[] args)
print(1, 2, 3, 4, 5, 7, 9, 10, 12);
public static void print(int ... nums)
System.out.print(nums[0]);
int idx = 1;
for(int i = 1; i < nums.length; i++, idx++)
if(nums[i] - nums[i - 1] != 1)
if(idx > 1)
System.out.print(" - " + nums[i - 1]);
System.out.print(", " + nums[i]);
idx = 0;
if(idx > 1)
System.out.println(" - " + nums[nums.length - 1]);
【讨论】:
我没有看到格式中的第一个数字。它显示 -5 而不是 1-5 @BadDeveloper 第一行代码打印第一个元素。可能你错过了!【参考方案9】:这是一个 Haskell 版本:
import Data.List
parseRange [] = ""
parseRange n =
let range = takeWhile (\x -> isInfixOf [x,x+1] n) n
in if not (null range)
then show (head range) ++ "-" ++ show (last range + 1)
++ (if length (tail n) > 1 then "," else "")
++ parseRange (drop (length range + 1) n)
else show (head n) ++ (if null (tail n) then "" else ",")
++ parseRange (drop 1 n)
输出:
*Main> parseRange [1,2,3,4,5,6,8,10,11]
"1-6,8,10-11"
【讨论】:
【参考方案10】:还有一种在 F# 中使用 fold 的方法 - 只是为了好玩。
let parseRange numbers =
numbers
|> Seq.fold
(fun list n ->
match list with
|(a,b) :: tail when b+1 = n -> (a, n) :: tail
|_ -> (n,n) :: list) []
|> List.rev
|> Seq.map (fun (a,b) -> if a = b then sprintf "%i" a else sprintf "%i-%i" a b)
|> String.concat ","
【讨论】:
以上是关于将 1,2,3,4,5,6,8,10,11 显示为 1-6,8,10-11的主要内容,如果未能解决你的问题,请参考以下文章
为啥 torch.FloatTensor([[[0,1,2],[3,4,5]],[[6,7,8],[9,10,11]]]) 的大小是 [2,2, 3]? [关闭]
已知如下数组: var arr = [ [1, 2, 2], [3, 4, 5, 5], [6, 7, 8, 9, [11, 12, [12, 13, [14] ] ] ], 10]; 编写一个程