代码随想录第一天

数组理论基础

数组存放在连续内存空间上的相同类型数据的集合

数组下标从0开始
数组内存空间的地址是连续的

Java 二维数组排布不是连续的

704 二分查找

Leetcode 704

考虑二分法的时机

数组有序,且无重复元素 (如果有重复元素,注意滑动窗口)

实现

  • 左闭右闭
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
class Solution{
public int binarySearch(int[] nums, int target){
if(target < nums[0] || target > nums[nums.length - 1]){
return -1
}

int left = 0, right = nums.length-1;

while(left <= right){
int mid = left + ((right - left) >> 1);
if (nums[mid] == target){
return mid;
} else if (nums[mid] < target){
left = mid + 1;
} else if (nums[mid] > target){
right = mid - 1;
}
}

return -1;
}
}
  • 左闭右开
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
class Solution{
public int binarySearch(int[] nums, int target){
if(target < nums[0] || target > nums[nums.length - 1]){
return -1;
}

int left = 0, right = nums.length;

while(left < right){
int mid = left + ((right - left) >> 1);

if (nums[mid] == target){
return mid;
} else if (nums[mid] < target){
left = mid + 1;
} else if (nums[mid] > target){
right = mid;
}
}
return -1;
}
}

循环不变量原则

注意右区间相关区别

  • 设置右起始值
  • 更新右值有区别
  • while条件的区别

27 移除元素

Leetcode 27

移除元素

数组元素删除过程复杂,因为数组长度不能更改,需要注意

实现

  1. 暴力解法
  • 查到val之后,把剩余元素用for loop向前覆盖一位
  • size自减1
  • i不自增,重新检查覆盖之后的元素
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
class Solution{
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];
}

size--;
i--;

}
}

return size;
}
}
  1. 快慢同向指针
  • 如果快指针找到val,慢指针不变
  • 如果快指针没找到val,慢指针位置被快指针位置元素覆盖,慢指针向下移一位
1
2
3
4
5
6
7
8
9
10
11
12
13
14
class Solution{
public int removeElement(int[] nums, int val){
int slowIndex = 0;

for (int fastIndex = 0; fastIndex < nums.length; fastIndex++){
if(val != nums[fastIndex]){
nums[slowIndex] = nums[fastIndex];
slowIndex++;
}
}

return slowIndex;
}
}
  1. 相向双指针
  • 右指针移到不是val的位置
  • 右指针的val覆盖左指针是val的位置

需要两个while循环 查找右指针第一个指向不是val的位置

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
class Solution{
public int removeElement(int[] nums, int val){
int left = 0, right = nums.length - 1;

while(right >= 0 && nums[right] == val) right--;

while(left <= right){
if (nums[left] == val){
nums[left] = nums[right--];
}

left++;

while(right >= 0 && nums[right] == val) right--;
}

return left;
}
}
  • 直接覆盖右指针的值,不需要判断右指针的值

不需要两个while循环

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
class Solution{
public int removeElement(int[] nums, int val){
int left = 0, right = nums.length - 1;

while(left <= right){
if(nums[left] == val){
nums[left] = nums[right];
right--;
} else {
left++;
}
}

return left;
}
}

记得更新右指针的位置