原题
Given a non-empty array of integers, return the third maximum number in this array. If it does not exist, return the maximum number. The time complexity must be in O(n).
Example 1:
Input: [3, 2, 1]
Output: 1
Explanation: The third maximum is 1.
Example 2:
Input: [1, 2]
Output: 2
Explanation: The third maximum does not exist, so the maximum (2) is returned instead.
Example 3:
Input: [2, 2, 3, 1]
Output: 1
Explanation: Note that the third maximum here means the third maximum distinct number.
Both numbers with value 2 are both considered as second maximum.
题目分析
找出第3个最大的,如果不存在第3个最大,返回当前最大。利用 .NET的Linq解题。
代码
public int GetThirdMax(int[] a)
{
int first = a.Max();
int[] a2 = a.Where(r => r != first).ToArray();
if (a2.Length == 0)
return first;
int second = a2.Max();
int[] a3 = a2.Where(r => r != second).ToArray();
if (a3.Length == 0)
return first;
return a3.Max();
}
题目延伸
找出第n个最大值,下面是代码,只用数组实现,不借助其他数据结构。新建一个NthMax对象,提供的API有2个,如下所示,
//插入元素到对象中
public void Insert(int target);
//报告第n个最大值
public int Nth{get;}
使用对象方法:
int[] a = new int[] { 1,2,6,7,8,9,0 };
NthMax myNth = new NthMax(5);
foreach (var item in a)
{
myNth.Insert(item);
}
int thirdMax = myNth.Nth;
对象完整实现源码:
/// <summary>
/// NthMax
/// </summary>
public class NthMax
{
#region 构造函数
public NthMax(int nth)
{
_nth = nth;
}
#endregion
#region 属性字段
private int[] _maxVals;
private int _nth;
#endregion
#region 私有方法
/// <summary>
/// 如果target不在_maxVals中,则找到它的插入位置;如果在直接返回-1
/// </summary>
/// <param name="target"></param>
/// <returns></returns>
private int searchInsertPos(int target)
{
int lo = 0;
int hi = _maxVals.Length;
while (lo < hi)
{
int mi = (lo + hi) >> 1;
if (target < _maxVals[mi]) //目标值不大于中间位置的数时,hi变小
hi = mi;
else if (target == _maxVals[mi])
return -1;
else if (target > _maxVals[mi]) //大于中间位置的值,lo加1
lo = lo + 1;
}
return lo;
}
/// <summary>
/// 在有序数组index处插入目标元素target
/// </summary>
/// <param name="index"></param>
/// <param name="target"></param>
private void insertAt(int index, int target)
{
int[] tmp = new int[_maxVals.Length + 1];
for (int i = 0; i < index; i++)
{
tmp[i] = _maxVals[i];
}
tmp[index] = target;
for (int i = index; i < _maxVals.Length; i++)
{
tmp[i + 1] = _maxVals[i];
}
_maxVals = tmp;
}
/// <summary>
/// 从beginIndex开始覆盖性后移1步
/// </summary>
/// <param name="beginIndex"></param>
private void moveBackward(int beginIndex)
{
if (beginIndex < 1)
return;
for (int i = 1; i <= beginIndex; i++)
{
_maxVals[i - 1] = _maxVals[i];
}
}
#endregion
#region 公有方法
public int Nth
{
get
{
return _maxVals.Length < _nth ?
_maxVals[_maxVals.Length - 1] : _maxVals[0];
}
}
/// <summary>
///
/// </summary>
/// <param name="target"></param>
public void Insert(int target)
{
if (_maxVals == null)
{
_maxVals = new int[1];
_maxVals[0] = target;
return;
}
if (_maxVals.Length < _nth)
{
int insertPos = searchInsertPos(target);
if (insertPos != -1)
{
insertAt(insertPos, target);
}
}
else if (_maxVals.Length == _nth)
{
int insertPos = searchInsertPos(target);
if (insertPos > 0)
{
if (insertPos == 0)
insertPos = 0;
moveBackward(insertPos - 1);
_maxVals[insertPos - 1] = target; //在空出来的位置处插入目标元素
}
}
}
#endregion
}