前言
- 系统的纪录一下刷算法的过程,之前一直半途而废,现在重新开始。话不多说,开冲!
数组理论基础
数组是存放在连续内存空间上的相同类型数据的集合
特点:
- 数组下标都是从0开始的。
- 数组内存空间的地址是连续的
因为数组的在内存空间的地址是连续的,所以我们在删除或者增添元素的时候,就难免要移动其他元素的地址,数组的元素是不能删的,只能覆盖
复习下java数组在内存中的情况:
java中数组的内存分配
1、二分查找
给定一个n个元素有序的(升序)整型数组nums 和一个目标值target ,写一个函数搜索nums中的 target,如果目标值存在返回下标,否则返回 -1。
- 输入: nums = [-1,0,3,5,9,12], target = 9
- 输出: 4
- 解释: 9 出现在 nums 中并且下标为 4
思路
有序数组,而且数组中无重复元素,这些二分法的前提条件
二分法容易想得到,但是就是经典一看就会,一做就错。
最重要的就是边界条件,(就在这里卡了半天,案例没问题,一提交力扣就错,tnnd)
代码随想录里面提供了两种思路:左闭右闭即[left, right],或者左闭右开即[left, right)
代码
左闭右闭
- while (left <= right) 要使用 <= ,因为left == right是有意义的,所以使用 <=
- if (nums[middle] > target) right 要赋值为 middle - 1,因为当前这个nums[middle]一定不是target,那么接下来要查找的左区间结束下标位置就是 middle - 1
个人感觉这个更好理解,也不容易出错
public static int search_1(int[] nums, int target) {
int left=0;
int right= nums.length-1;
while (left<=right){//闭区间,可能存在left == right
int mid=(right+left)/2;
if (target>nums[mid]){
left=mid+1;//因为mid所在的数字比较过了,这里要+1,下面同理
}else if (target<nums[mid]){
right=mid-1;
}else if (target==nums[mid]){
return mid;
}
}
return -1;
}
左闭右开
public static int search_2(int[] nums, int target) {
int left=0;
int right= nums.length;
while (left<right){
int mid=(right+left)/2;
if (nums[mid]<target){
left=mid+1;
}else if (target<nums[mid]){
right=mid;
}else if (target==nums[mid]){
return mid;
}
}
return -1;
}
2、移除元素
-
给你一个数组 nums和一个值 val,你需要 原地 移除所有数值等于val的元素,并返回移除后数组的新长度。
-
不要使用额外的数组空间,你必须仅使用 O(1) 额外空间并 原地 修改输入数组。
-
元素的顺序可以改变。你不需要考虑数组中超出新长度后面的元素
-
nums = [3,2,2,3], val = 3
-
2, nums = [2,2]
-
nums = [0,1,2,2,3,0,4,2], val = 2
-
5, nums = [0,1,4,0,3]
思路
数组的元素在内存地址中是连续的,不能单独删除数组中的某个元素,只能覆盖
这里使用双指针法(之前刷过,但忘了具体怎么使用)
自己写时候的思路过程:
用双指针,指什么呢?后面的元素不要,是不是可以一前一后?然后把前面要删除的元素移后面去,后面指针就指向一个不需要移除的元素(想的很好,但写的差点意思)
代码
public static int removeElement(int[] nums, int val) {
int left=0;
int right= nums.length-1;
//首先将右指针移到非移除元素下标(一开始这里我放在了for里面,用while确实好简洁)
while (right>=0&&nums[right]==val){right--;}
while (left<=right){
if (nums[left]==val){
int temp=nums[left];
nums[left]=nums[right];
nums[right]=temp;
right--;
}
left++;
//左右指针元素移了之后,右指针要指向一个非移除元素(就是这里没想到)
while (right>=0&&nums[right]==val){right--;}
}
return left;
}
小感悟
二分错了4次,对比边界条件一无所知
移除元素试了两次没写出来,看题解去了
今天等于说一天没写出来,还是写之前写过了题目,淦!!!