977.有序数组的平方
在非理想情况下,数组元素的绝对值特征符合凹陷型(先递减,再递增),可以理解为“两个有序平方数组”的有序合并问题。两个读指针分别指向首尾,比较数值并将较大的逆序填入。
class Solution {
public int[] sortedSquares(int[] nums) {
int r1 = 0, r2 = nums.length - 1;
int w = r2;
int[] ans = new int[r2 + 1];
while (r1 <= r2) {
if (Math.abs(nums[r2]) >= Math.abs(nums[r1])) {
ans[w] = nums[r2] * nums[r2];
w--;
r2--;
} else {
ans[w] = nums[r1] * nums[r1];
w--;
r1++;
}
}
return ans;
}
}
59.螺旋矩阵II
模拟填写流程,设置偏移量和方向,按照右下左上循环,试探边界更改方向。
class Solution {
public int[][] generateMatrix(int n) {
int dir = 0;
int x = 0, y = 0;
int[] dx = new int[]{0, 1, 0, -1};
int[] dy = new int[]{1, 0, -1, 0};
int[][] m = new int[n][n];
for (int i = 1; i <= n * n; i++) {
m[x][y] = i;
if (x + dx[dir] >= n || x + dx[dir] < 0 || y + dy[dir] >= n || y + dy[dir] < 0 || m[x + dx[dir]][y + dy[dir]] != 0) {
dir = (dir + 1) % 4;
}
x = x + dx[dir];
y = y + dy[dir];
}
return m;
}
}
*209.长度最小的子数组
初次尝试:前缀和+二分
class Solution {
public int minSubArrayLen(int target, int[] nums) {
int n = nums.length;
int[] sum = new int[n + 1];
for (int i = 1; i <= n; i++) {
sum[i] += nums[i - 1] + sum[i - 1];
}
if (sum[n] < target) return 0;
int lo = 1;
int hi = n;
while (lo < hi) {
int mid = lo + hi >>> 1;
boolean flag = false;
for (int i = 0; i + mid <= n; i++) {
if (sum[i + mid] - sum[i] >= target) {
flag = true;
break;
}
}
if (flag) hi = mid;
else lo = mid + 1;
}
return lo;
}
}
看视频思路二次尝试:暴力臃肿版本
class Solution {
public int minSubArrayLen(int target, int[] nums) {
int sum = 0;
int min = Integer.MAX_VALUE;
for (int end = 0; end < nums.length; end++) {
sum += nums[end];
if (sum >= target) {
// [0, end]
min = Math.min(min, end + 1);
int tmp = sum;
for (int begin = 0; begin < end; begin++) {
if (tmp - nums[begin] >= target) {
tmp -= nums[begin];
// (begin, end] / [begin+1, end]
min = Math.min(min, end - begin);
} else {
break;
}
}
}
}
return sum < target ? 0 : min;
}
}
逻辑简化版本:双指针暴力
class Solution {
public int minSubArrayLen(int target, int[] nums) {
int sum_prefix = 0;
int min = Integer.MAX_VALUE;
for (int end = 0; end < nums.length; end++) {
// summation of [0, end]
sum_prefix += nums[end];
// summation of [begin, end]
int begin = 0;
int sum_slide = sum_prefix;
while (sum_slide >= target) {
min = Math.min(min, end - begin + 1);
// reduce the slide window into [begin+1, end]
sum_slide -= nums[begin];
begin++;
}
}
return sum_prefix < target ? 0 : min;
}
}
滑动窗口:
class Solution {
public int minSubArrayLen(int target, int[] nums) {
int begin = 0;
// summation of elements in sldie window
int sum = 0;
int ans = Integer.MAX_VALUE;
for (int end = 0; end < nums.length; end++) {
sum += nums[end];
while (sum >= target) {
ans = Math.min(ans, end - begin + 1);
// reduce hop length implicitly
// there is no need to set begin=0 repeatedly
sum -= nums[begin++];
}
}
return ans == Integer.MAX_VALUE ? 0 : ans;
}
}