代码随想录一刷-Day02
LeetCode977.有序数组的平方
一开始只能想到暴力解法——先平方然后排序
实际上只要看清一件事:原数组已经经过排序了,那平方后的最大值就在数组的两端
,那只要将最大值逐个放入新数组中就可以了
这是巧妙而朴实的想法
public int[] sortedSquares(int[] nums) {
if (nums == null || nums.length == 0) {
return nums;
}
int[] newNums = new int[nums.length];
// 左右指针
int left = 0, right = nums.length - 1;
int newLast = newNums.length - 1;
// 平方后,数组的最大值不是在最左边就是在最右边,这是已排序的数组的特性
while (left <= right) {
int leftV = nums[left] * nums[left];
int rightV = nums[right] * nums[right];
if (leftV < rightV) {
newNums[newLast--] = rightV;
right--;
} else {
newNums[newLast--] = leftV;
left++;
}
}
return newNums;
}
时间复杂度:O(n)
空间复杂度:O(n)
LeetCode209.长度最小的子数组
很尴尬,没有仔细审题,以为要求子数组的和要等于 target,实际上是 >=target
我的 Code :
public int minSubArrayLen(int target, int[] nums) {
if (nums == null || nums.length == 0) {
return 0;
}
// 滑动窗口?
int left = 0, right = 1;
int sum = nums[left];
int len = (sum == target) ? 1 : Integer.MAX_VALUE;
while (right <= nums.length) {
if (sum == target) {
len = Math.min((right - left), len);
sum -= nums[left];
left++;
} else if (sum > target) {
// 和超过,收紧窗口
sum -= nums[left];
left++;
} else {
// 和未满,伸展窗口
if (right >= nums.length) {
break;
}
sum += nums[right];
right++;
}
}
return (len == Integer.MAX_VALUE) ? 0 : len;
}
如果题目要求等于的话,我的解答就没问题了吧
卡哥的 Code :
// Carl的滑动窗口
public int minSubArrayLen(int s, int[] nums) {
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;
}
时间复杂度:O(n)
空间复杂度:O(1)
关于时间复杂度为什么是 n,卡哥的说法如下:
不要以为for里放一个while就以为是O(n^2)啊, 主要是看每一个元素被操作的次数,每个元素在滑动窗后进来操作一次,出去操作一次,每个元素都是被操作两次,所以时间复杂度是 2 × n 也就是O(n)
LeetCode59.螺旋矩阵II
螺旋矩阵主要关注边界值问题,需要确定边界点由哪个方法处理
public int[][] generateMatrix(int n) {
// 螺旋矩阵需要处理好边界问题
// 确定每一条边左闭右开,上闭下开
int[][] nums = new int[n][n];
int x = 0, y = 0;
int type = 1; // 1-上,2-右,3-下,0-左
int offset = 0;
for (int i = 1; i <= n * n; i++) {
if (x == n || y == n) {
break;
}
switch (type % 4) {
case 1:
nums[x][y] = i;
if (y++ == n - offset - 2) {
type++;
}
break;
case 2:
nums[x][y] = i;
if (x++ == n - offset - 2) {
type++;
}
break;
case 3:
nums[x][y] = i;
if (y-- == offset + 1) {
type++;
}
break;
case 0:
nums[x][y] = i;
if (x-- == offset + 1) {
type++;
offset++;
x += 1;
y += 1;
}
break;
}
}
return nums;
}
我的解法是逐个点进行遍历
卡哥的解法是逐条边进行遍历,则要嵌套循环
class Solution {
public int[][] generateMatrix(int n) {
int loop = 0; // 控制循环次数
int[][] res = new int[n][n];
int start = 0; // 每次循环的开始点(start, start)
int count = 1; // 定义填充数字
int i, j;
while (loop++ < n / 2) { // 判断边界后,loop从1开始
// 模拟上侧从左到右
for (j = start; j < n - loop; j++) {
res[start][j] = count++;
}
// 模拟右侧从上到下
for (i = start; i < n - loop; i++) {
res[i][j] = count++;
}
// 模拟下侧从右到左
for (; j >= loop; j--) {
res[i][j] = count++;
}
// 模拟左侧从下到上
for (; i >= loop; i--) {
res[i][j] = count++;
}
start++;
}
if (n % 2 == 1) {
res[start][start] = count;
}
return res;
}
}
时间复杂度 O(n^2): 模拟遍历二维矩阵的时间
空间复杂度 O(1)