代码随想录自刷:数组篇
704.二分查找
思路:采用二分查找,注意查找的区间,个人习惯用[left, right]。
有一点要注意while判断条件是否包含=,根据题目要求是查找符合的下标,所以可以出现left=right的情况发生,算出当前mid下标是自己(left=right),判断自己是否等于目标值
时间复杂度:O(logn)
class Solution {
public int search(int[] nums, int target) {
int left = 0, right = nums.length - 1;
int mid;
while (left <= right) {
mid = left + (right - left) / 2;
if (nums[mid] == target) {
return mid;
} else if (nums[mid] < target) {
left = mid + 1;
} else {
right = mid - 1;
}
}
return -1;
}
}
27.移除元素
数组的特性,数组的内存地址是连续的,无法删除数组中某个元素,只能将其覆盖掉!直接覆盖要如何实现操作?也是用两个指针来完成!
个人采用的是快慢指针(也可以用双向指针:相向双指针法改变数组中元素顺序,快慢指针法不改变数组中元素顺序)
快指针一直遍历元素,当当前元素不等于删除元素时,慢指针指向的元素被赋值为当前元素值,然后慢指针++,如此直到快指针走完数组,此时慢指针就表示当前新数组的长度!
class Solution {
public int removeElement(int[] nums, int val) {
int left=0;
for(int right=0;right<nums.length;right++){
if(nums[right]!=val){
nums[left]=nums[right];
left++;
}
}
return left;
}
}
补充:双向指针写法:
//相向双指针法
class Solution {
public int removeElement(int[] nums, int val) {
int left = 0;
int right = nums.length - 1;
while(right >= 0 && nums[right] == val) right--; //将right移到从右数第一个值不为val的位置
while(left <= right) {
if(nums[left] == val) { //left位置的元素需要移除
//将right位置的元素移到left(覆盖),right位置移除
nums[left] = nums[right];
right--;
}
left++;
while(right >= 0 && nums[right] == val) right--;
}
return left;
}
}
977.有序数组的平方
思路:既然会用双指针,就用双指针解决!(数组很多问题都可以考虑双指针!效率更快)
根据题意:数组是递增的(包含负数),这样当前最大值只会在数组两头之一:
- 谁最大谁先放到新数组中(从后往前加入)
- 指向最大元素的指针此时往前or往后走,另一个指针不变,继续下一次的比较
public int[] sortedSquares(int[] nums) {
int[] res=new int[nums.length];
int left=0;
int right=nums.length-1;
int end=nums.length-1;
while(left<=right){
if(nums[left]*nums[left]>nums[right]*nums[right]){
res[end--]=nums[left]*nums[left];
left++;
}else{
res[end--]=nums[right]*nums[right];
right--;
}
}
return res;
}
209.长度最小的子数组(滑动窗口)
不考虑暴力双for解法,重点在滑动窗口!滑动窗口内的容量是有限的:
- 当窗口内的元素累加超过该容量时,就从头去掉元素。直到小于容量为止
- 当窗口内的元素累加小于该容量时,就从尾加入元素。直到超过容量为止
滑动窗口其实也是靠两个指针来实现!一个指向头部,一个指向尾部。
public int minSubArrayLen(int target, int[] nums) {
int left=0;
int sum=0;
int size=Integer.MAX_VALUE;;
for(int i=0;i<nums.length;i++){
sum+=nums[i];
System.out.println(sum);
while(sum>=target){
size=Math.min(size,i-left+1);
sum-=nums[left];
left++;
}
}
return size==Integer.MAX_VALUE ? 0 : size;
}
59. 螺旋矩阵 II
一开始难以理解,但记得要一条边、一条边的处理!遇到转角统一交给自己处理or下一条处理!不能混搭
思路:j用于记录循环第几圈,从0开始。从上方左到右开始(每条边的最后一格子交给自己处理)
public int[][] generateMatrix(int n) {
int[][] res=new int[n][n];
int count=1,j=0; //j等于循环圈的次数从0开始
while(count<=n*n){
//i<3
for(int i=j;i<n-j;i++){
res[j][i]=count++;//i=2,j=0
}
// i=1,i<3
for(int i=j+1;i<n-j;i++){
res[i][n-j-1]=count++;//col=3-0-1=2
}
//i=1,i>=0
for(int i=n-j-2;i>=j;i--){
res[n-j-1][i]=count++; //row=2
}
//i=1,i>0
for(int i=n-j-2;i>j;i--){
res[i][j]=count++; //col=0
}
j++;
}
return res;
}