排序(双指针版)
- 题目链接:双指针之排序
- 我的解法:时间复杂度 O ( n ) O(n) O(n),空间复杂度 O ( n ) O(n) O(n)
class Solution {
public int[] sortedSquares(int[] nums) {
int len = nums.length;
int[] cpy = new int[len];
int i = 0;int idx = 0;
for(; i < len; i++)
{
if(nums[i] >= 0) break;
}
int j = i - 1;
int a = 0;int b = 0;
if(j >= 0)a = nums[j] * nums[j];
if(i < len)b = nums[i] * nums[i];
while(j >= 0 && i < len)
{
if(a <= b)
{
cpy[idx++] = a;
j--;
if(j >= 0)
a = nums[j] * nums[j];
}
else
{
cpy[idx++] = b;
i++;
if(i < len)
b = nums[i] * nums[i];
}
}
while(j >= 0){cpy[idx++] = a;j--;if(j >= 0)a = nums[j] * nums[j];}
while(i < len){
cpy[idx++] = b;i++;if(i < len)b = nums[i] * nums[i];}
return cpy;
}
}
双指针同向而行可以应用于最典型的二分排序,本题我的思路就采用了这个思想,往往需要额外空间作为结果集。
一开始本来想的是双向双指针,但那种题型一般不会需要额外空间,思维固化了
- 答案解法
class Solution {
public int[] sortedSquares(int[] nums) {
int l = 0;
int r = nums.length - 1;
int[] res = new int[nums.length];
int j = nums.length - 1;
while(l <= r){
if(nums[l] * nums[l] > nums[r] * nums[r]){
res[j--] = nums[l] * nums[l++];
}else{
res[j--] = nums[r] * nums[r--];
}
}
return res;
}
}
双指针相向而行一般使用于划分,这里用额外的结果集调整位置利用非递减也可实现排序
双指针之滑动窗口
- 题目链接:双指针之滑动窗口
- 我的解法:
class Solution {
public int minSubArrayLen(int target, int[] nums) {
int left = 0;int right = 0; int sum = 0;int len = nums.length;
for(int r = 0;r < nums.length; r++)
{
sum += nums[r];
if(sum >= target)
{
int tmp = sum;right = r;
while(left <= r && tmp >= target) {tmp-=nums[left++];}
if(tmp >= target && (right - left + 1) < len)
{len = right-left + 1;sum = tmp;}
}
}
return len;
}
}
总结:主要没想明白在什么时候更新左右边界,sum的值可以随便改变,同时每一次更新sum就意味着左右边界更新
同时要注意len初始化最大值的设置,没有想到可能还会有找不到子序列的情况
- 正确解法:时间复杂度为 O ( n ) O(n) O(n),空间复杂度为 O ( 1 ) O(1) O(1)
class Solution {
public int minSubArrayLen(int target, int[] nums) {
int left = 0;int right = 0; int sum = 0;int len = Integer.MAX_VALUE;
for(int right = 0;right < nums.length; r++)
{
sum += nums[right];
while(sum >= target)
{
len = Math.min(right-left+1, len);
sum -= nums[left++];
}
}
if(len > nums.length) return 0;
return len;
}
}
总结:双指针的滑动窗口问题,需要明确窗口内的元素的含义,窗口两端的元素含义以及什么时候更新并记录窗口
模拟
- 题目链接:数组模拟
- 我的解法:
class Solution {
public int[][] generateMatrix(int n) {
int ans[][] = new int[n][n];
int num = 1;
int left = 0;int up = 0; int down = n-1; int right = n-1;
int bound = n*n + 1;
for(int l = left; l <= right && num < bound; l++){ans[up][l] = num++;}
up++;
for(int u = up; u <= down && num < bound; u++){ans[u][right] = num++;}
right--;
for(int r = right; r >= left && num < bound; r--){ans[down][r] = num++;}
down--;
for(int d = down; d >= up && num < bound; d--){ans[d][left] = num++;}
left++;
return ans;
}
}
总结:模拟思想,本题更像剥洋葱,上下左右每撕一层就占掉一层,但是没有考虑每层不止撕一次,外面还要加上一层大判断终止在矩阵核心的地方为条件
- 正确解法:
class Solution {
public int[][] generateMatrix(int n) {
int ans[][] = new int[n][n];
int num = 1;
int left = 0;int up = 0; int down = n-1; int right = n-1;
while(left <= right && up <= down)
{
for(int l = left; l <= right; l++){ans[up][l] = num++;}
up++;if(up >down) break;
for(int u = up; u <= down; u++){ans[u][right] = num++;}
right--;if(left > right) break;
for(int r = right; r >= left; r--){ans[down][r] = num++;}
down--;if(up >down) break;
for(int d = down; d >= up; d--){ans[d][left] = num++;}
left++;if(left > right) break;
}
return ans;
}
}
总结:模拟类的题型重要在划分边界,想不清楚一定要举例模拟一下得到判断条件而且当while大判断条件涉及变量在内部变化时,内部注意判断变量可能先于外界大条件越界