数字线的C#实现
数字线的C#实现,c#,range,line-numbers,C#,Range,Line Numbers,NumberLine是一个表示数字行的类。我想在上面标出不同的数字范围。CheckRange方法应该返回10-25中我标记的部分和我没有标记的部分。在这种情况下,它应该返回未标记的10-20,以及标记的20-25 我怎样才能有效地实现这一点,哪一点做不到o(n) 多谢各位 注意:这不是作业。我需要这个用于我的自定义数据库实现事务。我正在独自学习编程解决方案很简单:将所有突出显示的值添加到or树。我的意思是,当您添加范围(1,3)时,在树中插入整数值1,2和3 检查范围时,只需查找端点值。这需要O
NumberLine
是一个表示数字行的类。我想在上面标出不同的数字范围。CheckRange
方法应该返回10-25
中我标记的部分和我没有标记的部分。在这种情况下,它应该返回未标记的10-20
,以及标记的20-25
我怎样才能有效地实现这一点,哪一点做不到o(n)
多谢各位
注意:这不是作业。我需要这个用于我的自定义数据库实现事务。我正在独自学习编程解决方案很简单:将所有突出显示的值添加到or树。我的意思是,当您添加范围(1,3)时,在树中插入整数值1,2和3 检查范围时,只需查找端点值。这需要O(logn)这比O(n)快得多
注意:插入和删除所有takeO(log n)解决方案很简单:将所有突出显示的值添加到or树。我的意思是,当您添加范围(1,3)时,在树中插入整数值1,2和3 检查范围时,只需查找端点值。这需要O(logn)这比O(n)快得多 注:插入和删除所有takeO(logn)O(n)的意思随元素的数量而变化 O(1)表示恒定时间 我也想不出一个O(1)的方法来实现这一点。O(n)的意思随着元素的数量而变化 O(1)表示恒定时间
我也想不出一个O(1)方式来实现这一点。好的,我明白你的意思了 使用非常大的位字段执行此操作 假设您可能的数字范围从1到64,这些数字中的每一个都对应于64位int上该位置的位(1是位0,2是位1) 如果在一个范围中添加一个数字,则打开该位(在您的示例中,您将打开位0到4和19到29) 现在,要检查一个数字范围,您需要在打开该范围的位的情况下创建另一个64位int,并对两位字段执行按位and(&)。结果中的1位是重叠范围 对于大于64的数字,只需放大位数(可能通过使用数组或整数列表) 希望这有帮助:) 更新:可扩展性 假设您使用的是64位体系结构,您可以在一次操作中使用64位和64位整数。理想情况下,您应该使用64位整数 现在,假设您可能的数字范围从1到64000,为此您需要1000个64位整数 现在让我们看几个用例
然而,使用这个算法,一般情况仍然是O(n)好的,我明白你的意思了 使用非常大的位字段执行此操作 假设您可能的数字范围从1到64,这些数字中的每一个都对应于64位int上该位置的位(1是位0,2是位1) 如果在一个范围中添加一个数字,则打开该位(在您的示例中,您将打开位0到4和19到29) 现在,要检查一个数字范围,您需要在打开该范围的位的情况下创建另一个64位int,并对两位字段执行按位and(&)。结果中的1位是重叠范围 对于大于64的数字,只需放大位数(可能通过使用数组或整数列表) 希望这有帮助:) 更新:可扩展性 假设您使用的是64位体系结构,您可以在一次操作中使用64位和64位整数。理想情况下,您应该使用64位整数 现在,假设您可能的数字范围从1到64000,为此您需要1000个64位整数 现在让我们看几个用例
然而,使用这种算法,一般情况下仍然是O(n)我不确定应用程序的具体细节,但我的直觉告诉我,这在数据库中处理会更好,因为它是基于集合的操作 即
选择
*
来自Numberline
哪里
编号\u组=@group\u id
标记=1
和编号>=@min\u范围
我不确定这个应用程序的具体细节,但我的直觉告诉我,在数据库中处理这个问题会更好,因为它是一个基于集合的操作
即
选择
*
来自Numberline
哪里
编号\u组=@group\u id
标记=1
和编号>=@min\u范围
和数字使用哈希集:
但它应该会让您走上正确的轨道。使用哈希集:
但它应该是g
NumberLine line = new NumberLine();
line.AddRange(1, 5);
line.AddRange(20, 30);
line.CheckRange(10, 25);
Select
*
from numberlines
where
number_group = @group_id
marked = 1
and number >= @min_range
and number <= @max_range
public class NumberLine : HashSet<int>
{
public void AddRange(int start, int end)
{
int count = (end-start)+1;
UnionWith(Enumerable.Range(start, count));
}
public IEnumerable<int> CheckRange(int start, int end)
{
NumberLine other = new NumberLine();
other.AddRange(start, end);
other.IntersectWith(this); // marked
// other.ExceptWith(this); // not marked
return other;
}
}
public string CheckRange(int start, int end)
{
NumberLine other = new NumberLine();
other.AddRange(start, end);
IEnumerable<int> marked = other.Intersect(this);
IEnumerable<int> notMarked = other.Except(this);
int markedMin = marked.Min();
int markedMax = marked.Max();
int notMarkedMin = notMarked.Min();
int notMarkedMax = notMarked.Max();
string markedString = (markedMin == markedMax)
? markedMin.ToString()
: string.Format("{0} - {1}", markedMin, markedMax);
string notMarkedString = (notMarkedMin == notMarkedMax)
? notMarkedMin.ToString()
: string.Format("{0} - {1}", notMarkedMin, notMarkedMax);
return string.Format("Marked: {0}\r\nNot Marked: {1}", markedString, notMarkedString);
}
Marked: 10-15, 20-25
Not Marked: 16-19
LineNumber {
List<Range> ranges;
aadRange(a,b);
// Loops through all ranges and calls isInRange on each method
isInRange(a);
//just iterates over isInRange from a to b
checkRange(a,b)
}
Range {
Range(a,b)
isInRange(a);
}
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
namespace NumberLine
{
class Program
{
static void Main(string[] args)
{
NumberLine line = new NumberLine();
line.AddRange(1, 5);
line.AddRange(10, 12);
line.AddRange(20, 30);
List<Range> ranges = line.CheckRange(10, 25);
foreach (Range r in ranges)
{
for (int i = r.Start; i <= r.End; i++)
{
Console.WriteLine(i);
}
}
}
}
class Range
{
public int Start;
public int End;
}
class NumberLine
{
private SortedList<int, Range> Ranges = new SortedList<int, Range>();
public void AddRange(int start, int end)
{
if (Ranges.Count == 0)
{
Ranges.Add(start, new Range() { Start = start, End = end });
}
else
{
foreach (Range currentRange in Ranges.Values)
{
if (start <= currentRange.Start)
{
if (end >= currentRange.End)
{
currentRange.Start = start;
currentRange.End = end;
}
else
{
currentRange.Start = start;
}
Ranges.RemoveAt(start);
Ranges.Add(start, currentRange);
break;
}
else
{
if (start <= currentRange.End)
{
currentRange.End = end;
break;
}
else
{
Ranges.Add(start, new Range(){ Start = start, End = end });
break;
}
}
}
}
}
public List<Range> CheckRange(int start, int end)
{
List<Range> result = new List<Range>();
foreach (Range currentRange in Ranges.Values)
{
if (start <= currentRange.End)
{
if (end <= currentRange.End)
{
result.Add(new Range() { Start = currentRange.Start, End = end });
break;
}
else
{
if (start <= currentRange.Start)
{
result.Add(new Range() { Start = currentRange.Start, End = currentRange.End });
}
else
{
result.Add(new Range() { Start = start, End = currentRange.End });
}
}
}
}
return result;
}
}
}