摘要:讲解数组理论基础,以具体题目来解析其实际应用,包括二分查找、双指针法移除元素、双指针法求有序数组平方后的有序数组以及双指针法求满足一定条件的长度最小的子数组四个常见基本算法。
目录
理论基础
定义
数组是存放在连续内存空间上的相同类型数据的集合。
特点
- 数组通过索引的方式获取索引对应的数据,方便查找和访问;
- 数组索引从0开始,且内存空间连续;
- 由于数组内存空间连续,在删除和插入元素时,难免会移动其他元素的地址;
- 数组的元素不能删除,只能覆盖。
应用
二分查找
题目:给定一个有序的无重复元素整型数组array和一个目标值value,写一个方法搜索array中的 value,如果目标值存在返回下标,否则返回-1。
二分法:不断二分区间最终找到目标值。
该题目满足数组二分查找的两要素:有序数组、目标元素唯一。
该方法代码如下(C#):
/// <summary>
/// 二分法查找升序数组的元素
/// </summary>
/// <param name="array"></升序整型数组>
/// <param name="value"></查找值>
/// <returns></returns>
public static int twoDivide(int[] array, int value)
{
int left = 0;//左区间,初始为0
int right = array.Length - 1;//右区间,初始为最大索引
/*双闭区间二分法*/
while (left <= right)
{
int divide = left + (right - left) / 2;
if (array[divide] > value)
{
right = divide - 1;
}
else if (array[divide] < value)
{
left = divide + 1;
}
else
{
return divide;
}
}
return -1;
}
双指针法移除元素
题目:给定一个整型数组ary和值value,用双指针法求ary移除所有值为value的元素后的数组。(移除后剩下的元素不用管)
双指针法思路:用一个快指针和一个慢指针完成数组元素移除,快指针负责寻找不含移除元素的新元素,慢指针负责更新数组元素。
代码如下(C):
void RemoveValue(int* ary,int length,int value)
{
int slow = 0;
for (int fast = 0;fast < length;fast++)
{
if (ary[fast] != value)
{
ary[slow] = ary[fast];
slow++;
}
}
}
双指针法求有序数组平方后的有序数组
题目:给定一个非降序数组ary,用双指针法求ary所有元素平方后的非降序数组。
双指针法思路:定义一个与ary长度相同的新数组,一个指针从头到尾走,另一个指针从尾到头走,边走边比大小,按大小顺序放入新数组中。
代码如下(C):
int* SquareAry(int* ary, int length)
{
int* squareAry;
int left = 0;
int right = length - 1;
int i = 0;
squareAry = (int*)malloc(sizeof(int) * length);
while (left <= right)
{
if (ary[left] * ary[left] < ary[right] * ary[right])
{
squareAry[i] = ary[right] * ary[right];
right--;
}
else
{
squareAry[i] = ary[left] * ary[left];
left++;
}
i++;
}
return squareAry;
}
双指针法求满足一定条件的长度最小的子数组
题目:给定一个整型数组ary和一个正整数k,用双指针法找出该数组中满足其和 ≥ k 的长度最小的连续子数组,并返回其长度。如果不存在符合条件的子数组,返回 0。
双指针法思路:定义两个从头到尾方向走的指针,前指针先往前走,判断前后指针包尾的子数组和是否大于等于k,若达到条件,记录该子数组长度,开始移动后指针,这样,前后指针走完,就找出了满足条件的长度最小的子数组了。
代码如下(C):
int MinLength(int* ary, int length, int k)
{
int later = 0;
int sum = 0;
int minLength = length;
for (int formar = 0;formar < length;formar++)
{
sum += ary[formar];
while (sum >= k)
{
int subLength = formar - later + 1;
if (subLength < minLength)
{
minLength = subLength;
}
sum -= ary[later];
later++;
}
}
return minLength;
}
小结
数组是非常简单的一种数据结构,但不熟悉基本算法的话,使用起来也会不顺手。掌握数组及其基本算法,可以事半功倍,既逻辑清晰,又简明高效。编程不仅要以能不能实现为目的,并且还要以低算法复杂度为目的,这样才是优秀的代码!
每篇寄语
懒惰行动得如此缓慢,贫穷很快就能超过它。. —— 富兰克林