采用的Java语言,一些分析也是用于Java,请注意。
代码随想录 (programmercarl.com)
数组的特点是在内存空间上连续且数据类型一样。
数组知道下标,get(index)时的时间复杂度为O(1),但并不意味着它寻找某个元素是O(1),而是O(n){不采用一些算法遍历去寻找的话}
正由于数组在内存空间上是连续的,所以必须在增加、删除元素的时候,移动其他元素来保持连续
对于二维数组:
public class Test {
public static void main(String[] args) {
int [] x1 = {1,2,3};
int [][] x2 = {{1, 2, 3}, {3, 4, 5}, {6, 7, 8}, {9,9,9}};
System.out.println(x1.getClass().getName());
System.out.println(">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>");
System.out.println(x2.getClass().getName());
System.out.println(">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>");
System.out.println(x2[0]);
System.out.println(x2[1]);
System.out.println(x2[2]);
System.out.println(x2[3]);
}
}
结果:
[I
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
[[I
[I@378bf509
[I@5fd0d5ae
[I@2d98a335
[I@16b98e56
Java中,数组属于对象,那么可以看到上面代码中x1和x2的类名,就是数组,数组并不是基本数据类型,所以不管是一维数组还是二维数组,都是存在堆中的。
对于每个小数组(每一行),他的内存地址并没有规则,说明二维数组的每一个行的内存地址没有关系
随想录中的解释是这样的:
对于二分法,最重要的就是理解两个要点:
1、用二分法的必要条件
对于这个,二分法必须建立在数组中元素是有序且无重复元素的,这个必须保证才能用二分法
2、通过定义区间判断边界
下面围绕第二点做出论述
1、while循环中 left < right 还是 <=right
2、
如果nums[mid] > traget ,那么我们应该更新右面的指针,right指针是rigit = middle 还是middle-1
同样,nums[mid] 在区间搜索的时候,要确定是 [ ) 还是[ ],个人平常就喜欢使用左闭又开,因为这样计算index 的时候,很方便 比如 0 1 2 3 4 5),区间范围是[0,5),那么这6个元素,实际上存在的只有0到4这5个, 那么算长度的话,直接5-0 =5 比如 3 4 5 6 7) 7-3 =4,长度就是 4(3到6这几个数) while循环中,保持对刚开始定义的区间的[] [)确定下来,每次循环都按照左闭右开的去做题,就是循环不变量,坚持后面边界处理的时候,都是左闭右开。 二分查找复杂度为Logn级别的,做题的时候可以留意 704二分查找 35. 搜索插入位置 - 力扣(LeetCode) 给定一个排序数组和一个目标值,在数组中找到目标值,并返回其索引。如果目标值不存在于数组中,返回它将会被按顺序插入的位置。 请必须使用时间复杂度为 注意排序数组,目标值,logn,可以想到用二分查找 27. 移除元素 - 力扣(LeetCode) 数组的移除不是简单的删除,因为数组是一个连续的空间,删除一个元素,需要移动后面的元素,保证数组的连续 暴力删除的话,比如123456 删除4 需要先找到4,然后再把后面向前移动 这个也是比较好理解的,快指针遍历,满指针存放新的数组。 理解这里就可以 了 今天作业完成,后续还需要做这些题 随想录34题题解,这里我有些理解不了的地方,群友可以探讨一下。 代码随想录 (programmercarl.com) 解决问题
1、明确区间
2、循环不变量
3、两种写法(加上了我自己理解的注释)
public class Test {
public static void main(String[] args) {
int [] x1 = {1,2,3};
System.out.println(binarySearch1(x1, 2));
System.out.println(binarySearch2(x1, 1));
}
/**
* [ ]
* @param arr
*/
public static int binarySearch1(int [] arr,int target){
//[] 右边界要等于最后一位
int left = 0,right = arr.length-1;
//left=right是因为[]的时候,合法,比如[1,1]
while (left<=right){
//主要两个int值相加可能越界的问题
int mid = (left+right)/2;
if(arr[mid]>target){
//左闭右闭,以为arr[mid]已经确定大于target了,所以不能包含这个值,所以right要=mid-1
right = mid - 1;
}else if(arr[mid] < target){
//同上,因为确定不在区间内了,所以也不能包含
left = mid + 1;
}else {
return mid;
}
}
//没找到
return -1;
}
/**
* [ )
*/
public static int binarySearch2(int [] arr,int target){
//【) right指针就可以直接等于length了。!
int left = 0,right = arr.length;
// [1,1) 不合法,所以不加=号
while (left < right){
int mid = (left+right)/2;
if(arr[mid]>target){
// [) arr[mid]大于target,所以可以直接等于,比如 3 大于 2 ,right = 3的话也没事,因为取不到3
right = mid;
}else if(arr[mid] < target){
// 【)左面是开区间,所以确定mid的值不在目标里的话,就必须+1跳过去
left = mid+1;
}else {
return mid;
}
}
return -1;
}
}
复杂度
做题
704二分查找
class Solution {
public int search(int[] nums, int target) {
//【) right指针就可以直接等于length了。!
int left = 0,right = nums.length;
// [1,1) 不合法,所以不加=号
while (left < right){
int mid = (left+right)/2;
if(nums[mid]>target){
// [) arr[mid]大于target,所以可以直接等于,比如 3 大于 2 ,right = 3的话也没事,因为取不到3
right = mid;
}else if(nums[mid] < target){
// 【)左面是开区间,所以确定mid的值不在目标里的话,就必须+1跳过去
left = mid+1;
}else {
return mid;
}
}
return -1;
}
}
35.搜索插入位置
O(log n)
的算法。class Solution {
public int searchInsert(int[] nums, int target) {
int left = 0,right = nums.length;
while (left < right){
int mid = (left+right)/2;
if(nums[mid]>target){
right = mid;
}else if(nums[mid] < target){
left = mid+1;
}else {
return mid;
}
}
// 1 5 3 6 target = 2
// l=0,r=3, m = 1 ,( nums[mid] = 3 ) > target --> r = mid=2;
// l = 0, r = 2 m = 0 (nums[mid]=1) > target -->l = mid+1 = 1;
// l = 1,r = 2. m = 1 -(nums[mid=3 > 2)------>r = mid =1
// l = r = 1 ==插入位置
return left;
}
}
27.移除元素
暴力解法
class Solution {
public int removeElement(int[] nums, int val) {
int size = nums.length;
for(int i =0;i
快慢指针
class Solution {
public int removeElement(int[] nums, int val) {
int slow = 0;
for(int fast = 0;fast
日后补充