1.知识点
1.1数组基础理论
数组中的地址是连续的
对于二维数组:
c++语言中,二维数组也是连续的
java语言中,二维数组不是连续的
1.2二分查找
对于有序数组相关的问题,可以考虑二分法
1.3双指针
双指针(快慢指针,双向指针)在考察数组,链表,字符串等操作的题目中较常用
2.刷题
704.二分查找
LeetCode链接:704. 二分查找 - 力扣(LeetCode)
题目描述
方法1:二分查找
package daimasuixiangshuati.day01_shuzu;
/**
* @Author LeiGe
* @Date 2023/9/20
* @Description todo
*/
public class ErFenChaZhao704_1 {
/**
* 二分查找
*
* @param nums
* @param target
* @return
*/
public static int search(int[] nums, int target) {
//区间左侧
int left = 0;
//区间右侧
int right = nums.length - 1;
// 采用[左闭右闭的区间策略]
while (left <= right) {
// 求出区间中点位置
int mid = left + ((right - left) >> 1);
// nums[mid] > target: 说明target在mid左侧,那么更新区间右边界
if (nums[mid] > target) {
right = mid - 1;
}
// nums[mid] < target: 说明target在右侧,那么更新区间右边界
else if (nums[mid] < target) {
left = mid + 1;
} else {
return mid;
}
}
return -1;
}
}
时间复杂度:O(logN)
空间复杂度:O(1)
注意点:在计算区间中点位置的时候用int mid = left + ((right - left) >> 1)代替int mid = (left + right) / 2;
这样的好处是:1.可以避免相加溢出 2.采用位运算加速
27.移除元素
LeetCode链接:27. 移除元素 - 力扣(LeetCode)
题目描述
方法1:暴力
package daimasuixiangshuati.day01_shuzu;
/**
* @Author LeiGe
* @Date 2023/9/20
* @Description todo
*/
public class YiChuYuanSu27_1 {
/**
* 方法1:暴力-每次删除一个元素后,数组中此位置后的所有数都往前移动
*
* @param nums
* @param val
* @return
*/
public int removeElement(int[] nums, int val) {
int size = nums.length;
for (int i = 0; i < size; i++) {
// 发现是要删除的元素,数组中所有元素向前移动一位
if (nums[i] == val) {
for (int j = i + 1; j < size; j++) {
nums[j - 1] = nums[j];
}
// 下标i处的值被删除了,所以i要往前移动一位
i--;
size--;
}
}
return size;
}
}
时间复杂度:O(N^2)
空间复杂度:O(1)
方法2:快慢指针-不改变原数组中元素相对位置
package daimasuixiangshuati.day01_shuzu;
/**
* @Author LeiGe
* @Date 2023/9/20
* @Description todo
*/
public class YiChuYuanSu27_2 {
/**
* 方法2:快慢指针
* 如果快指针的值不等于val,那么就将快指针处的值移动到慢指针处
* 最后慢指针所处的位置就是删除元素后数组的长度
* @param nums
* @param val
* @return
*/
public static int removeElement(int[] nums, int val) {
int size = nums.length;
int slowIndex = 0;
for (int fastIndex = 0; fastIndex < size; fastIndex++) {
if (nums[fastIndex] != val) {
nums[slowIndex] = nums[fastIndex];
slowIndex++;
}
}
return slowIndex;
}
}
时间复杂度:O(N)
空间复杂度:O(1)
方法3:相向双指针-改变了原数组中元素相对位置
package daimasuixiangshuati.day01_shuzu;
/**
* @Author LeiGe
* @Date 2023/9/20
* @Description todo
*/
public class YiChuYuanSu27_3 {
/**
* 方法3:相向双指针法
* 0.左指针在最左边,右指针在最右边
* 1.从左边找到等于val的位置
* 2.从右边找到不等于val的位置
* 3.将右边不等于val位置的数覆盖到左边等于val位置
* 4.循环结束后,left指针所处的位置就是新数组的长度
*
* @param nums
* @param val
* @return
*/
public static int removeElement(int[] nums, int val) {
int left = 0;
int right = nums.length - 1;
while (left <= right) {
//找左边等于val的元素
while (left <= right && nums[left] != val) {
left++;
}
//找右边不等于val的元素
while (left <= right && nums[right] == val) {
right--;
}
// 将右边不等于val的元素覆盖到左边等于val的元素
if (left < right) {
nums[left] = nums[right];
left++;
right--;
}
}
return left;
}
}
时间复杂度:O(N)
空间复杂度:O(1)
3.小结
1.对于有序的数组,可以考虑二分
2.双指针常用的类型有快慢指针,相向双指针