- Notifications
You must be signed in to change notification settings - Fork 1.6k
/
Copy pathFastSearcher.cs
79 lines (67 loc) · 2.42 KB
/
FastSearcher.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
usingSystem;
usingUtilities.Exceptions;
namespaceAlgorithms.Search;
/// <summary>
/// The idea: you could combine the advantages from both binary-search and interpolation search algorithm.
/// Time complexity:
/// worst case: Item couldn't be found: O(log n),
/// average case: O(log log n),
/// best case: O(1).
/// Note: This algorithm is recursive and the array has to be sorted beforehand.
/// </summary>
publicclassFastSearcher
{
/// <summary>
/// Finds index of first item in array that satisfies specified term
/// throws ItemNotFoundException if the item couldn't be found.
/// </summary>
/// <param name="array">Span of sorted numbers which will be used to find the item.</param>
/// <param name="item">Term to check against.</param>
/// <returns>Index of first item that satisfies term.</returns>
/// <exception cref="ItemNotFoundException"> Gets thrown when the given item couldn't be found in the array.</exception>
publicintFindIndex(Span<int>array,intitem)
{
if(array.Length==0)
{
thrownewItemNotFoundException();
}
if(item<array[0]||item>array[^1])
{
thrownewItemNotFoundException();
}
if(array[0]==array[^1])
{
returnitem==array[0]?0:thrownewItemNotFoundException();
}
var(left,right)=ComputeIndices(array,item);
var(from,to)=SelectSegment(array,left,right,item);
returnfrom+FindIndex(array.Slice(from,to-from+1),item);
}
private(intLeft,intRight)ComputeIndices(Span<int>array,intitem)
{
varindexBinary=array.Length/2;
int[]section=
{
array.Length-1,
item-array[0],
array[^1]-array[0],
};
varindexInterpolation=section[0]*section[1]/section[2];
// Left is min and right is max of the indices
returnindexInterpolation>indexBinary
?(indexBinary,indexInterpolation)
:(indexInterpolation,indexBinary);
}
private(intFrom,intTo)SelectSegment(Span<int>array,intleft,intright,intitem)
{
if(item<array[left])
{
return(0,left-1);
}
if(item<array[right])
{
return(left,right-1);
}
return(right,array.Length-1);
}
}