代码随想录训练营D1-数组篇 day1 |力扣704二分查找、27移除元素
文章中图片均来自于代码随想录代码随想录
1. 数组理论基础
1.定义:数组是存放在连续内存空间上的相同类型数据的集合。
2.较于链表的优势:随机存取。
3.二维数组:先行后列,横行竖列
3.1 c++
(使用C++要注意vector 和 array的区别,vector的底层实现是array,严格来讲vector是容器,不是数组。)
c++中二维数组在内存中是连续的
void test_arr() {
int array[2][3] = {
{0, 1, 2},
{3, 4, 5}
};
cout << &array[0][0] << " " << &array[0][1] << " " << &array[0][2] << endl;
cout << &array[1][0] << " " << &array[1][1] << " " << &array[1][2] << endl;
}
int main() {
test_arr();
}
//输出结果如下:是连续的
//0x7ffee4065820 0x7ffee4065824 0x7ffee4065828
//0x7ffee406582c 0x7ffee4065830 0x7ffee4065834
3.2 java中二维数组在内存中不是连续的
public static void test_arr() {
int[][] arr = {{1, 2, 3}, {3, 4, 5}, {6, 7, 8}, {9,9,9}};
System.out.println(arr[0]);
System.out.println(arr[1]);
System.out.println(arr[2]);
System.out.println(arr[3]);
}
2.Leetcode704 二分查找
1.二分查找:
数组nums内元素升序排列,给定目标元素target,若数组中有对应元素则返回其下标,若无该元素则返回-1。
2.基本思路:
在头、尾分别设置一个指针;计算出中间位置元素的下标 mid。若nums[mid]的值比targat小,则在后半段中继续找target;否则在前半段中找。
3.边界问题
在写代码时,关于数组下标的边界问题,大致有两种思路。思路一:左闭右闭 即[0, length-1]
思路二:左闭右开 即[0, length)
在写代码前先选定一个思路,然后在过程中都按着这种思路去写边界。
2.1 左闭右闭
public int search(int[] nums, int target) {
//左闭右闭
int i = 0;
int j = nums.length - 1;
int mid;
//while循环中是 i <= j? 还是 i < j ?
//考虑极限情况,在左闭右闭的条件下,i,j为同一下标是否合法?
//[1,1] 是合法的,所以i,j可以相等
while(i <= j){
mid = (i + j) / 2;
if(nums[mid] == target){//找到目标值,返回
return mid;
}else if(nums[mid] < target){//数组中间值 < 目标值;则目标值在右半侧
//条件为左闭右闭,且右侧区间的左端点为mid + 1;
i = mid + 1;
}else {//nums[mid] > target
j = mid -1;
}
}
return -1;
}
2.2 左闭右开
//左闭右开[0, length)
public int search1(int[] nums, int target) {
int i = 0;
int j = nums.length;//右开
int mid;
//while循环中是 i <= j? 还是 i < j ?
//考虑极限情况,在左闭右开的条件下,i,j为同一下标是否合法?
//[1,1) 不合法的,所以i,j 不能相等
while(i < j){
mid = (i + j) / 2;
if(nums[mid] == target){//找到目标值,返回
return mid;
}else if(nums[mid] < target){//数组中间值 < 目标值;则目标值在右半侧
//条件为左闭右开,且右侧区间的左端点为mid + 1;
i = mid + 1;
}else {//nums[mid] > target
//条件为左闭右开,左侧区间右端点应取到mid - 1;但这里是右开,所以j=mid;
j = mid;
}
}
return -1;
}
3.Leetcode27 移动元素
思路:快慢指针。
这里for循环中的i即为快指针,n为慢指针。快指针是为了找要存入的元素,而慢指针是在记录新数组中元素的位置。
//给你一个数组 nums 和一个值 val,你需要 原地 移除所有数值等于 val 的元素,并返回移除后数组的新长度。
public int removeElement(int[] nums, int val) {
int n = 0;//待插入位置指针。数值不为val时,后移;数值为val 不动。
int length = nums.length;
//遍历时将 元素 移动到待插入位置
for(int i = 0; i < length; ++i){
nums[n] = nums[i];
if(nums[i] != val){
++n;
}
}
return n;
}