【Leecode】代码随想录数组篇day2(双指针(排序&滑动窗口)& 模拟)

排序(双指针版)

  • 题目链接:双指针之排序
  • 我的解法:时间复杂度 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大判断条件涉及变量在内部变化时,内部注意判断变量可能先于外界大条件越界

  • 7
    点赞
  • 18
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值