1. 今日收获:数组理论基础,二分查找,快慢指针,相向双指针
2. 数组理论基础:
(1)数组是存放在连续内存空间上的相同类型数据的集合。
(2)Java二维数组的排列方式
3. 二分查找,例题 704. 二分查找
题目:704. 二分查找
思想:从数组的两个端点开始,每次将目标值和区间中间的元素相比,根据比较结果可以减小区间范围为原来的一半
方法一:区间左闭右闭
class Solution {
public int search(int[] nums, int target) {
int left=0;
int right=nums.length;
// 左闭右开
while(left<right){
int mid=left+((right-left)>>1);
// 相等
if (nums[mid]==target){
return mid;
}
if (nums[mid]>target){ // 目标在左区间
right=mid;
continue;
}
if (nums[mid]<target){ // 目标在右区间
left=mid+1;
continue;
}
}
return -1;
}
}
方法二:区间左闭右开
class Solution {
public int search(int[] nums, int target) {
int left=0;
int right=nums.length;
// 左闭右开
while(left<right){
int mid=left+((right-left)>>1);
// 相等
if (nums[mid]==target){
return mid;
}
if (nums[mid]>target){ // 目标在左区间
right=mid;
continue;
}
if (nums[mid]<target){ // 目标在右区间
left=mid+1;
continue;
}
}
return -1;
}
}
总结:需要掌握循环不变量:区间的开闭。如果端点处是开区间,则目标值不在端点处;如果是闭区间,则目标值不在端点处,就需要考虑相等的情况。上面两种方法的不同之处在于right初始值的定义,循环终止条件的判断,以及缩小区间范围时与mid的关系
4. 快慢指针,例题 27. 移除元素
题目:27. 移除元素
思想:方法一暴力解法:首先遍历数组,遇到等于val的元素就移动数组后面的元素,但是要记得移动之后修改数组的长度和指针的位置;方法二是快慢指针,快指针出去"闯荡江湖",寻找满足条件的"好苗子",找到之后就赋值给"守家"的慢指针
方法一:暴力解法
class Solution {
public int removeElement(int[] nums, int val) {
// 暴力解法,两个for循环
int len=nums.length;
for (int i=0;i<len;i++){
// 判断是否需要移除元素
if (nums[i]==val){
// 覆盖元素
for (int j=i;j<len-1;j++){
nums[j]=nums[j+1];
}
i--; // * 移动指针,减少长度
len--;
}
}
return len;
}
}
方法二:快慢指针
class Solution {
public int removeElement(int[] nums, int val) {
// 双指针法
int slow=0;
int len=nums.length;
for (int fast=0;fast<len;fast++){
if (nums[fast]!=val){ // 满足条件
nums[slow++]=nums[fast]; // 慢指针赋值
}
}
return slow;
}
}
总结:快慢指针可以在一个数组上遍历一次完成任务,之后在遇到类似需要两个for操作时,可以考虑这样的解法,一个指针"寻找",一个指针"收集"。
5. 相向双指针,例题 977.有序数组的平方
题目:977.有序数组的平方
思想:定义两个指针分别指向数组的头和尾,哪一个指针指向元素的平方比较大,就将数据写入结果数组,然后再移动对应的指针,指向此方向的下一个元素
方法:相向双指针
class Solution {
public int[] sortedSquares(int[] nums) {
int len=nums.length;
int[] result=new int[len];
int k=len-1;
int i=0; // 相向双指针
int j=len-1;
while (i<=j){
if (nums[i]*nums[i]>nums[j]*nums[j]){
result[k--]=nums[i]*nums[i];
i++;
}else {
result[k--]=nums[j]*nums[j];
j--;
}
}
return result;
}
}
总结:同向指针和双向指针的区别在于方向的不同,27题可以从头到尾遍历数组,977题中最大元素可能是头尾元素的平方,两个指针都向中间聚拢。