代码随想录:数组
数组是存储在连续内存空间上的相同类型数据集合,地址必须连续,下标从0开始
因为地址连续所以想要删除某一元素就要移动后续所有元素的地址所以数组中的元素不能删除只能覆盖
实际使用注意最大下标为.Length属性的止-1
力扣704:二分查找
public class Solution {
public int Search(int[] nums, int target) {
int left=0, right=nums.Length-1;
//左右边界
while (left<=right ) //闭区间
{
int middle=left+(right-left)/2;
if (nums[middle]>target){
right=middle-1;、
//根据查找数据值大小决定下次的边界下标
}
else if(nums[middle]<target){
left=middle+1;
}
else{
return middle;
//找到目标返回middle即为下标
}
}
return -1;
//找不到返回-1
}
}
有序且无重复元素的查找,此时使用二分查找
力扣27:移除元素
//双指针,常用于数组与链表
public 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+=1;、
//在每次循环中判断快指针指向的元素值是否为要删除的值,不是则把值赋给慢指针指的元素,是则快指针继续移动
}
}
return left;
}
}
最开始做本题时选择对每次快指针指向目标值时快慢指针所指元素交换,多出了许多判断操作,在时间复杂度相同的情况下判断操作较多对程序用时差距影响很大,再一次循环中完成且判断操作少才能优化时间
本题中直接对原数组进行操作,空间复杂度O(1)。
返回值是int,实际操作为
// nums 是以“引用”方式传递的。也就是说,不对实参作任何拷贝
int len = removeElement(nums, val);
// 在函数里修改输入数组对于调用者是可见的。
// 根据你的函数返回的长度, 它会打印出数组中 该长度范围内 的所有元素。
for (int i = 0; i < len; i++) {
print(nums[i]);
}
来源:力扣(LeetCode)
链接:https://leetcode.cn/problems/remove-element
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
力扣209:长度最小的子数组
public class Solution {
public int MinSubArrayLen(int target, int[] nums) {
int left=0,right=0,count=100001;
long add=nums[right];
//滑动窗口
while(right<nums.Length){
if(add<target){
right++;
if(right!=nums.Length){
add+=nums[right];
//窗口右边界移动
}
}
else{
count=Math.Min(count,right-left+1);
add-=nums[left];
left++;
//窗口左边界移动
}
}
if(count==100001){
count=0;
//目标数据最大为10^5因此设定count初始值为10^5+1,若最后未找到结果则按题目要求返回0
}
return count;
}
}
滑动窗口可视为双指针的一种,通过不断调整子数组大小降低时间复杂度
力扣59:螺旋矩阵II
public class Solution {
public int[][] GenerateMatrix(int n) {
int[][] cells=new int[n][];
for(int a=0;a<n;a++){
cells[a]=new int[n];
//初始化一个交错数组,满足题目中的返回值类型
}
int x=0,y=0;//起始位置
int i=0,j=0;
int offset=1;//每条边遍历长度用
int count=1;//填入的数字
int loop=n/2;//进行循环多少圈
int mid=n/2;//矩阵中心坐标
while(loop-->0){
i=x;
j=y;
for(j=y;j<y+n-offset;j++){ //y+n-offset,y起始位置,n一条边的元素数量,offset扣除的本次遍历这一行不填入数字的格子数
cells[i][j]=count++;//填数
}
for(i=x;i<x+n-offset;i++){
cells[i][j]=count++;
}
for(;j>y;j--){
cells[i][j]=count++;
}
for(;i>x;i--){
cells[i][j]=count++;
}
offset+=2;//转了一圈,下次循环就要少填两个格子
x++;
y++;//下次循环开始在下一圈,起点从[0,0]变成[1,1]
}
if(n%2!=0){
cells[mid][mid]=count;//若为奇数阶的矩阵要手动填入最中心的元素
}
return cells;
}
}
暴力循环,注意循环过程中坚持循环不变量,即每次循环的一条边都是相同区间,这里选择左闭右开