算法day02
977. 有序数组的平方
- 题目链接:https://leetcode.cn/problems/squares-of-a-sorted-array/description/
- 第一眼看到题目的思路
- 找0或者负变正的交界点,然后从中间往两边散发比较找较大值,算平方,直到某一边到头,再整另一边。(没写出来)
- 第三四眼看题目的思路
- 先把数组的所有负数变成正数,然后用冒泡排序,然后直接把数组原地平方。
- 数组先变正数再排序再原地平方的实现
class Solution {
public int[] sortedSquares(int[] nums) {
for(int i = 0;i<nums.length;i++){
if(nums[i]<0) {
nums[i] = -nums[i];
}
}
//冒泡排序
sort(nums);
for(int i = 0;i<nums.length;i++){
nums[i] = nums[i]*nums[i];
}
return nums;
}
public int[] sort(int [] nums){
for(int i = 0;i<nums.length;i++){
for(int j = 0;j<nums.length-i-1;j++){
if(nums[j]>nums[j+1]){
int temp = nums[j];
nums[j] = nums[j+1];
nums[j+1] = temp;
}
}
}
return nums;
}
}
- 暴力法存在的问题或难点
- 问题:速度和效率
- 难点:无
- 看答案的代码实现
class Solution {
public int[] sortedSquares(int[] nums) {
int left = 0,right = nums.length-1;
int flag = nums.length-1;
int [] res = new int[nums.length];
while(left<=right){
if(nums[left]*nums[left]>nums[right]*nums[right]){
res[flag] = nums[left]*nums[left];
left++;
}else{
res[flag] = nums[right]*nums[right];
right--;
}
flag--;
}
return res;
}
}
- 存在的问题或难点
主要理解双指针的精髓,在排序数组中都可以方便使用。 - 总结
- 感觉自己的思路过于死板。都能大费周章去中间找正负交界点了,为啥不能直接从两边往中间找。
- 既然都能排序了,为啥不直接先平方了再排序,非要先把负数变成正数再排序再平方?
自己这个脑子有时候不知道咋想的。
209. 长度最小的子数组
- 题目链接:https://leetcode.cn/problems/minimum-size-subarray-sum/description/
- 第一眼看到题目的思路:两个指针,不断找两个指针之间的和,如果和满足条件就更新长度,不断缩小长度再往后找,找最小的长度。
- 第三四眼看到题目的思路:没想法,完全没想法,暴力法还有三个超时的通过不了,唉,有点小难。
- 暴力方法实现
假的滑动窗口,本质还是两层for循环
class Solution {
public int minSubArrayLen(int target, int[] nums) {
int left = 0,right = 0;
int minLen = nums.length+1;
while(left<=right && right<nums.length){
if(sum(nums,left,right)<target){
right++;
}else{
int step = right - left + 1;
minLen = minLen>step?step:minLen;
left++;
}
}
if(minLen==nums.length+1){
return 0;
}
return minLen;
}
public int sum(int [] nums,int start,int end){
int sum = 0;
for(;start<=end;start++){
sum += nums[start];
}
return sum;
}
}
- 看答案代码:
class Solution {
public int minSubArrayLen(int target, int[] nums) {
int left = 0,right = 0;
int minLen = nums.length+1;
int sum = 0;
while(right<nums.length){
//记录滑动窗口区间数值的和
sum+=nums[right++];
//准备开始移动左边的元素了
while(sum>=target){
int len = right - left;
minLen = minLen>len?len:minLen;
sum-=nums[left];
left++;
}
}
if(minLen == nums.length+1) return 0;
return minLen;
}
}
- 要点
- 这道题其实一开始想的暴力法和答案的暴力法不一样
- 自己写双指针法的时候写成暴力法了
- 真正的滑动窗口,其实本质上也类似于是双指针。只不过滑动窗口要不断滑动。
59.螺旋矩阵II
- 题目链接:https://leetcode.cn/problems/spiral-matrix-ii/
- 第一眼看到题目的思路:完全没有任何思路
- 第三四眼看到题目的思路:左闭右开
- 代码
class Solution {
public int[][] generateMatrix(int n) {
//起始点(start,start)
int start = 0;
//循环次数
int loop = 0;
//偏移量
int val = 1;
//数组
int [][] arr = new int[n][n];
int count = 1;
//循环次数小于n/2才可以
while(loop<n/2){
for(int j = start;j<n-val;j++){
arr[start][j] = count;
System.out.println(start+","+j+","+count);
count++;
}
for(int i = start;i<n-val;i++){
arr[i][n-val] = count;
System.out.println(i+","+(n-val)+","+count);
count++;
}
for(int j = n - val;j>start;j--){
arr[n-val][j] = count;
System.out.println((n-val)+","+j+","+count);
count++;
}
for(int i = n - val;i>start;i--){
arr[i][start] = count;
System.out.println(i+","+start+","+count);
count++;
}
start++;
val++;
loop++;
}
if(n%2==1){
arr[start][start] = count;
}
return arr;
}
}
如果转一圈,左右都会少一条边,整个正方形的宽度减2,一共宽度是n,每次减2,就是循环n/2次
三道题,晚上八点写到凌晨00.43