1。 我做了一个带字符串数组的函数,
{"foo", "#123", "#124", "bar", "#125", "#126"}
创建一个新数组,其数字转换为范围:
{"foo", "#123:126", "bar"}
并返回:
"foo,#123:126,bar"
请注意,它不会更改两个数字的范围(不应将{"#1", "#2"}
更改为{"#1:#2"}
)。这是因为#1:#2
和#1,#2
占用相同的尺寸。
顺序对于所有值都很重要,不包括在范围内压缩的值。例如,在{#6, #5, #1, foo, #2, #3}
中,#2
和#3
会被#1
压扁,这没关系,但其余的应该有相同的顺序。
以下是我的实现,由于多次.Contains
调用,因此效率非常低。
using System;
using System.Linq;
using System.Collections.Generic;
class Program
{
static void Main(string[] args)
{
var ids = new string[] {
"foo", //output: unmodified
"#60", "#59", "#61", "#62", //from integer is in between, output: #59:#62
"#12", "#14", "#17", "#13", "#18", "#bar", "#19", "#20", //two ranges and string intertwined, output: #12:#14,#17:#20,#bar
"#25", "#26", //output: unmodified
"#39", "#38", //output: unmodified
"baz", //output: unmodified
"#12", "#13", "#14" //duplicate sequences, output: #12:#14
};
//this is what the function should output when fed `ids`:
Console.WriteLine("foo,#59:#62,#12:#14,#17:#20,#bar,#25,#26,#38,#39,baz,#12:#14");
Console.WriteLine(Compress(ids));
Console.Read();
}
static string Compress(IEnumerable<string> IDs)
{
var result = new List<string>();
var ignore = new HashSet<string>();
foreach (var item in IDs)
{
if (ignore.Contains(item)) continue;
var id = item;
if (id.StartsWith("#"))
{
int fromInt;
if (int.TryParse(id.Substring(1), out fromInt))
{
var less1 = $"#{fromInt - 1}";
var plus1 = $"#{fromInt + 1}";
var hasPlus1 = IDs.Contains(plus1);
if (IDs.Contains(less1) && hasPlus1) continue;
var plus2 = $"#{fromInt + 2}";
if (hasPlus1 && IDs.Contains(plus2))
{
ignore.Add(plus1);
ignore.Add(plus2);
var toInt = fromInt + 2;
while (IDs.Contains($"#{toInt + 1}"))
{
toInt += 1;
ignore.Add($"#{toInt}");
}
id = $"#{fromInt}:#{toInt}";
}
}
}
result.Add(id);
}
return string.Join(",", result);
}
}
有人能告诉我如何才能提高效率?
答案 0 :(得分:0)
以下是执行此操作的一种方法(以下代码中的注释):
$result = $mj->campaign([
'FromEmail' => 'sender email'
]);
var_dump($result);
答案 1 :(得分:0)
我最终得到了两遍算法。主要挑战是选择支持快速键查找和重复键的正确数据结构。 Dictionary<int, List<int>
看起来太占用空间,所以我决定使用链接列表,例如由Dictionary<int, int>
保存第一个键位置的结构,以及一个带链接和处理信息的单独数组。
第一遍准备处理结构,第二遍发出结果。由于每个元素仅被解析一次(包括使用具有O(1)时间复杂度的字典查找的范围检查),因此算法IMO的时间复杂度应为O(N)。
除此之外,它与您的非常相似,因此可能被视为优化实施。
enum EntryType { Single, Range, Unknown }
struct Entry
{
public string Value;
public int Number;
public int Next; // position of the next value with the same number
public EntryType Type;
}
static string Compress(IEnumerable<string> input)
{
var entryList = input.Select(value => new Entry { Value = value }).ToArray();
var numberQueue = new Dictionary<int, int>(entryList.Length); // Key=number, Value=position
for (int pos = entryList.Length - 1; pos >= 0; pos--)
{
var value = entryList[pos].Value;
int number;
if (value.Length > 1 && value[0] == '#' && int.TryParse(value.Substring(1), out number))
{
int nextPos;
if (!numberQueue.TryGetValue(number, out nextPos)) nextPos = -1;
entryList[pos].Number = number;
entryList[pos].Type = EntryType.Unknown;
entryList[pos].Next = nextPos;
numberQueue[number] = pos;
}
}
var output = new StringBuilder();
for (int pos = 0; pos < entryList.Length; pos++)
{
var entryType = entryList[pos].Type;
if (entryType == EntryType.Range) continue; // already processed
var number = entryList[pos].Number;
int startPos = pos, endPos = pos, prevCount = 0, nextCount = 0;
if (entryType == EntryType.Unknown)
{
for (int prevPos; numberQueue.TryGetValue(number - prevCount - 1, out prevPos) && prevPos >= 0; startPos = prevPos, prevCount++) { }
for (int nextPos; numberQueue.TryGetValue(number + nextCount + 1, out nextPos) && nextPos >= 0; endPos = nextPos, nextCount++) { }
entryType = prevCount + nextCount >= 2 ? EntryType.Range : EntryType.Single;
for (int offset = -prevCount; offset <= nextCount; offset++)
{
var nextNumber = number + offset;
int nextPos = numberQueue[nextNumber];
entryList[nextPos].Type = entryType;
numberQueue[nextNumber] = entryList[nextPos].Next;
}
}
if (output.Length > 0) output.Append(',');
if (entryType == EntryType.Single)
output.Append(entryList[pos].Value);
else
output.Append(entryList[startPos].Value).Append(':').Append(entryList[endPos].Value);
}
return output.ToString();
}