1.2.2 #
解答 #
同样实现了一个 Interval1D 类(位于 Geometry 库)。
JAVA 版本参考:http://algs4.cs.princeton.edu/12oop/Interval1D.java.html。
直接调用其中的 Intersect() 方法即可
代码 #
Interval1D 类: #
/// <summary>
/// 一维闭区间。
/// </summary>
public class Interval1D
{
/// <summary>
/// 优先以起点升序排序,起点相同时按照终点升序排序。
/// </summary>
/// <value>优先以起点升序排序,起点相同时按照终点升序排序。</value>
public static readonly Comparer<Interval1D> MinOrder = new MinEndpointComparer();
/// <summary>
/// 优先以终点升序排序,起点相同时按照起点升序排序。
/// </summary>
/// <value>优先以终点升序排序,起点相同时按照起点升序排序。</value>
public static readonly Comparer<Interval1D> MaxOrder = new MaxEndpointComparer();
/// <summary>
/// 以区间长度升序排序。
/// </summary>
/// <value>以区间长度升序排序。</value>
public static readonly Comparer<Interval1D> LengthOrder = new LengthComparer();
/// <summary>
/// 区间起点。
/// </summary>
/// <value>区间起点。</value>
/// <remarks>这个属性是只读的。</remarks>
public double Min { get; }
/// <summary>
/// 区间终点。
/// </summary>
/// <value>区间终点。</value>
/// <remarks>这个属性是只读的。</remarks>
public double Max { get; }
/// <summary>
/// 构造函数。
/// </summary>
/// <param name="lo">一维区域的下界。</param>
/// <param name="hi">一维区域的上界。</param>
public Interval1D(double lo, double hi)
{
if (double.IsInfinity(lo) || double.IsInfinity(hi))
{
throw new ArgumentException("Endpoints must be finite");
}
if (double.IsNaN(lo) || double.IsNaN(hi))
{
throw new ArgumentException("Endpoints cannot be NaN");
}
if (lo <= hi)
{
Min = lo;
Max = hi;
}
else
{
throw new ArgumentException("Illegal interval");
}
}
/// <summary>
/// 一维区域的长度。
/// </summary>
/// <returns>返回长度。</returns>
public double Length()
{
return Max - Min;
}
/// <summary>
/// 判断目标区间是否被本区间包含。
/// </summary>
/// <param name="that">需要判断是否被包含的区间。</param>
/// <returns>若 <paramref name="that"/> 被本区间包含则返回 <c>true</c>,否则返回 <c>false</c>。</returns>
public bool Contains(Interval1D that)
{
return Min < that.Min && Max > that.Max;
}
/// <summary>
/// 目标值是否处在区域内。如果目标值在区域内则返回 True,否则返回 False。
/// </summary>
/// <param name="x">需要判断的值。</param>
/// <returns>若 <paramref name="x"/> 被本区间包含则返回 <c>true</c>,否则返回 <c>false</c>。</returns>
public bool Contains(double x)
{
return x >= Min && x <= Max;
}
/// <summary>
/// 判断两个区域是否相交。
/// </summary>
/// <param name="that">需要判断相交的另一个区域。</param>
/// <returns>如果相交则返回 True,否则返回 False。</returns>
public bool Intersect(Interval1D that)
{
if (Max < that.Min || that.Max < Min)
return false;
return true;
}
/// <summary>
/// 绘制一维区间。
/// </summary>
/// <param name="g">原点在左下方,y轴向上,x轴向右的画布。</param>
/// <param name="y">绘制一维区间的 y轴 坐标。</param>
public void Draw(Graphics g, int y)
{
var a = new Point((int)Min, y);
var b = new Point((int)Max, y);
g.DrawLine(Pens.Black, a, b);
}
/// <summary>
/// 将区域转换为 string,返回形如 "[lo, hi]" 的字符串。
/// </summary>
/// <returns>形如 "[<see cref="Min"/>, <see cref="Max"/>]" 的字符串。</returns>
public override string ToString()
{
var s = "[" + Min + ", " + Max + "]";
return s;
}
/// <summary>
/// 判断两个区间是否相等。
/// </summary>
/// <param name="obj">相比较的区间。</param>
/// <returns>如果区间相等则返回 <c>true</c>,否则返回 <c>false</c>。</returns>
public override bool Equals(object obj)
{
if (obj == this)
{
return true;
}
if (obj == null)
{
return false;
}
if (obj.GetType() != GetType())
{
return false;
}
var that = (Interval1D)obj;
return Math.Abs(Min - that.Min) < double.Epsilon * 5 && Math.Abs(Max - that.Max) < double.Epsilon * 5;
}
/// <summary>
/// 返回区间的哈希代码。
/// </summary>
/// <returns>返回区间的哈希代码。</returns>
public override int GetHashCode()
{
var hash1 = Min.GetHashCode();
var hash2 = Max.GetHashCode();
return 31 * hash1 + hash2;
}
private class MinEndpointComparer : Comparer<Interval1D>
{
public override int Compare(Interval1D a, Interval1D b)
{
Debug.Assert(a != null, nameof(a) + " != null");
Debug.Assert(b != null, nameof(b) + " != null");
if (a.Min < b.Min)
{
return -1;
}
if (a.Min > b.Min)
{
return 1;
}
if (a.Max < b.Max)
{
return -1;
}
if (a.Max > b.Max)
{
return 1;
}
return 0;
}
}
private class MaxEndpointComparer : Comparer<Interval1D>
{
public override int Compare(Interval1D a, Interval1D b)
{
Debug.Assert(a != null, nameof(a) + " != null");
Debug.Assert(b != null, nameof(b) + " != null");
if (a.Max < b.Max)
{
return -1;
}
if (a.Max > b.Max)
{
return 1;
}
if (a.Min < b.Min)
{
return -1;
}
if (a.Min > b.Min)
{
return 1;
}
return 0;
}
}
private class LengthComparer : Comparer<Interval1D>
{
public override int Compare(Interval1D a, Interval1D b)
{
Debug.Assert(a != null, nameof(a) + " != null");
var alen = a.Length();
Debug.Assert(b != null, nameof(b) + " != null");
var blen = b.Length();
if (alen < blen)
{
return -1;
}
if (alen > blen)
{
return 1;
}
return 0;
}
}
}
Main #
Console.WriteLine("Type the value of N:");
var n = int.Parse(Console.ReadLine());
var intervalList = new List<Interval1D>();
if (n < 2)
{
Console.WriteLine("Make sure there are at least 2 Intervals");
return;
}
// 读取并建立间隔数组
Console.WriteLine("Type the data, make sure there is a space between two numbers.\nExample: 0.5 1");
for (var i = 0; i < n; i++)
{
var temp = Console.ReadLine();
var lo = double.Parse(temp.Split(' ')[0]);
var hi = double.Parse(temp.Split(' ')[1]);
if (lo > hi)
{
var t = lo;
lo = hi;
hi = t;
}
intervalList.Add(new Interval1D(lo, hi));
}
// 判断是否相交并输出
for (var i = 0; i < n; i++)
{
for (var j = i + 1; j < n; j++)
{
if (intervalList[i].Intersect(intervalList[j]))
{
Console.WriteLine($"{intervalList[i]} {intervalList[j]}");
}
}
}