文章来源:代码随想录 数组Part2
977.有序数组的平方
做题小结
这道题总体来说逻辑比较清晰,暴力先一边循环得到平方,然后使用排序排成升序。这里排序使用了冒泡。
for(int i = 0;i<nums.length;i++){
nums[i] = nums[i]*nums[i];
}
for(int i=1;i<nums.length;i++){
for(int j=i;j > 0;j--){
if(nums[j] < nums[j-1]){
int temp = nums[j];
nums[j] = nums[j-1];
nums[j-1] = temp;
}
}
}
return nums;
后期改进时间,使用Arrays.sort()快排。
for(int i = 0;i<nums.length;i++){
nums[i] = nums[i]*nums[i];
}
Arrays.sort(nums);
return nums;
代码随想录方法
接昨天的移除元素的题,这里也可以用到双指针法,具体实现为一头一尾两个指针,逐步向中间合拢,因为原数组是升序且有负数,那么最大的值肯定在一头一尾开始看。既然从最大的值开始找起,那么新的数组由大到小来更新。因为要求要升序,那么初始下标为nums.length-1。
int l = 0;
int r = nums.length - 1;
int[] res = new int[nums.length];
int index = nums.length - 1;
while(l <= r){
if(nums[l] * nums[l] > nums[r] * nums[r]){
res[index] = nums[l] * nums[l];
l++;
}else{
res[index] = nums[r] * nums[r];
r--;
}
index--;
}
return res;
209.长度最小的子数组
仔细审题很重要!!
这道题看到的第一想法是使用两个指针构造一个滑动窗口,具体实现如下。在实现过程中,一开始一直出现case不过的情况,后来一看发现是审题的时候把>=target看成了=target,遂解决。
int l = 0;
int r = 0;
int sum = nums[0];
int min = nums.length + 1;
while(r < nums.length){
if (sum == target){
min = Math.min(r - l + 1,min);
if(r < nums.length - 1){
sum += nums[++r];
sum -= nums[l++];
}else{
break;
}
}else if(sum < target){
if(r < nums.length - 1){
sum += nums[++r];
}else{
break;
}
}else{
min = Math.min(r - l + 1,min);
sum -= nums[l++];
}
}
if (min == nums.length + 1){
return 0;
}
return min;
但感觉不够简便,因此转向随想录。
随想录代码
int left = 0;
int sum = 0;
int result = Integer.MAX_VALUE;
for (int right = 0; right < nums.length; right++) {
sum += nums[right];
while (sum >= s) {
result = Math.min(result, right - left + 1);
sum -= nums[left++];
}
}
return result == Integer.MAX_VALUE ? 0 : result;
59.螺旋矩阵II
螺旋矩阵的实现逻辑一如既往比较难以理清,经过随想录的讲解可知,这次也要应用循环不变量 - 左闭右开,左开右闭。
还有一个很重要的点是,这里需要将每一圈都当做一个独立的左闭右开循环,不能相互影响。因此在n的情况下,会有n/2圈需要做左闭右开循环,每圈的区间大小统一依次-1。
根据理解,实现代码如下
int[][] nums = new int[n][n];
int startX = 0, startY = 0; // X代表行起点,Y代表猎奇点,每一圈的起始点
int count = 1; // 矩阵中需要填写的数字
int loop = 1; // 记录当前的圈数
int i, j; // j 代表列, i 代表行;
while(loop <= n/2){
for(j = startY;j < n-startY-1;j++){
nums[startX][j] = count;
count++;
}
for(i = startX;i< n-startX-1;i++){
nums[i][n-startY-1] = count;
count++;
}
for(j = n-startY-1;j > startY;j--){
nums[n-startY-1][j]=count;
count++;
}
for(i=n-startX-1;i > startX;i--){
nums[i][startY] = count;
count++;
}
startX++;
startY++;
loop++;
}
if (n % 2 == 1) { // n 为奇数时,单独处理矩阵中心的值
nums[startX][startY] = count;
}
return nums;
结语
数组的部分到这里就结束了,总体来说学到很多,其中对我来说最主要的还是循环区间不变量和双指针(或相向双指针)的概念和应用,需要后期继续拓展磨练。