题目:
http://weibo.com/1435323715/ycrmi0mpI
@belleveinvis : 刚才群里看到的一个编程题送各位:给定一个 array,求出里面最长的连续的一段,它由连续的数组成,顺序任意。例如 (5 1 3 2) 就返回 (1 3 2),(5 3 1 4 2) 就返回 (5 3 1 4 2)。@老赵 @装配脑袋 @朴灵
思路:
其实就两关键问题:
1.如何判断几个数字是由“连续的数字组成”
一堆数里如果没有相同的数字,而且这些数里最大数减最小数正好等于这堆数的数量(严格的说再减一),那他们就是由连续的数组成的。不信可以随便找几个数来验证这个逻辑。
2.解决了1之后,如何在整个数组中去用1的办法寻找所有满足条件的子数组。
穷举不可避免,只是尽量有点效率。我的做法是从左到右遍历数组。把遍历的那个数作为起点,往右按照上面的办法寻找满足条件的子数组,找到就缓存下来,下次找比它大的,从而得到满足条件的最长的一段。
解答(未做太多优化):
/// <summary>
/// new GetMaxChildArray(new int[] { 5, 6, 3, 1, 4, 2 }).Go()
/// </summary>
class GetMaxChildArray
{
int[] array;
List<int> maxChild = new List<int>();
/// <summary>
/// 初始化,传进来一个array
/// </summary>
/// <param name="_array"></param>
public GetMaxChildArray(int[] _array)
{
if (_array == null || _array.Length == 0)
throw new ArgumentException();
this.array = _array;
}
/// <summary>
/// GO!
/// </summary>
/// <returns></returns>
public int[] Go()
{
//关键:从首位遍历数组
for (int i = 0, length = this.array.Length; i < length - maxChild.Count; i++)
{
//然后从当前位(i)作为子数组起点,寻找满足要求的子数组
FindChindArrayFromIndex(i);
}
return maxChild.ToArray();
}
private void FindChindArrayFromIndex(int index)
{
int max = int.MinValue,
min = int.MaxValue,
reginSize = 0,
leftCount = this.array.Length - index,
current = 0;
Dictionary<int, bool> existedNumbers = new Dictionary<int, bool>();
for (int i = index, length = this.array.Length; i < length; i++)
{
current = this.array[i];
//退出条件1:碰上相同的数
if (existedNumbers.ContainsKey(current))
return;
existedNumbers.Add(current, true);
max = Math.Max(max, current);
min = Math.Min(min, current);
reginSize = max - min;
//退出条件2:此次碰上了不能搭配的最大最小数
if (reginSize > leftCount)
return;
//命中
if (reginSize == i - index && reginSize >= this.maxChild.Count)
{
this.maxChild = new List<int>();
for (int ii = index; ii <= i; ii++)
{
this.maxChild.Add(this.array[ii]);
}
}
}
}
/// new GetMaxChildArray(new int[] { 5, 6, 3, 1, 4, 2 }).Go()
/// </summary>
class GetMaxChildArray
{
int[] array;
List<int> maxChild = new List<int>();
/// <summary>
/// 初始化,传进来一个array
/// </summary>
/// <param name="_array"></param>
public GetMaxChildArray(int[] _array)
{
if (_array == null || _array.Length == 0)
throw new ArgumentException();
this.array = _array;
}
/// <summary>
/// GO!
/// </summary>
/// <returns></returns>
public int[] Go()
{
//关键:从首位遍历数组
for (int i = 0, length = this.array.Length; i < length - maxChild.Count; i++)
{
//然后从当前位(i)作为子数组起点,寻找满足要求的子数组
FindChindArrayFromIndex(i);
}
return maxChild.ToArray();
}
private void FindChindArrayFromIndex(int index)
{
int max = int.MinValue,
min = int.MaxValue,
reginSize = 0,
leftCount = this.array.Length - index,
current = 0;
Dictionary<int, bool> existedNumbers = new Dictionary<int, bool>();
for (int i = index, length = this.array.Length; i < length; i++)
{
current = this.array[i];
//退出条件1:碰上相同的数
if (existedNumbers.ContainsKey(current))
return;
existedNumbers.Add(current, true);
max = Math.Max(max, current);
min = Math.Min(min, current);
reginSize = max - min;
//退出条件2:此次碰上了不能搭配的最大最小数
if (reginSize > leftCount)
return;
//命中
if (reginSize == i - index && reginSize >= this.maxChild.Count)
{
this.maxChild = new List<int>();
for (int ii = index; ii <= i; ii++)
{
this.maxChild.Add(this.array[ii]);
}
}
}
}
}