算法训练营 day2 数组 有序数组 长度最小的子数组 螺旋矩阵

算法训练营 day2 数组 |有序数组 长度最小的子数组 螺旋矩阵

有序数组的平方

双指针法的经典题目

977. 有序数组的平方 - 力扣(LeetCode)

给你一个按 非递减顺序 排序的整数数组 nums,返回 每个数字的平方 组成的新数组,要求也按 非递减顺序 排序。

​ 首先我们分析一下给出的nums的情况,无非就三种。1、全部为正整数。2、全部为负整数。3即有正整数又有负整数。

在这里插入图片描述

我们不难发现所有的数据平方后的最大值都分布在两端此时我们就可以使用双指针法来解决问题。

创造一个新数组(result)来存储排序比较后的数组,再设置一个flag来记录插入新数组的位置。设置两个指针分别指向数组的头和尾,然后继续比较。

如果A[left] * A[left] < A[right] * A[right] 那么result[k--] = A[right] * A[right]此时右指针-1。

如果A[left] * A[left] > A[right] * A[right] 那么result[k--] = A[left] * A[left]此时左指针+1。

如果A[left] * A[left] = A[right] * A[right]可以设置左或者右指针的值插入。

代码如下:

    public int[] sortedSquares(int[] nums) {
        int left = 0;
        int right = nums.length-1;
        int[] num = new int[nums.length];
        int flag = num.length-1;
        while (left<=right){
            if (nums[left]*nums[left]<nums[right]*nums[right]){
                num[flag--] = nums[right]*nums[right];
                right--;
            }else{
                num[flag--] = nums[left]*nums[left];
                left++;
            }
        }
        return num;
    }

长度最小的子数组

使用滑动窗口法。

209. 长度最小的子数组 - 力扣(LeetCode)

给定一个含有 n 个正整数的数组和一个正整数 target 。

找出该数组中满足其和 ≥ target 的长度最小的 连续子数组 [numsl, numsl+1, …, numsr-1, numsr] ,并返回其长度。如果不存在符合条件的子数组,返回 0 。

​ 所谓滑动窗口,其实也是双指针的一种。通过不断地调整子表地起始位置和终止位置。来得到我们想要地效果。

在这里插入图片描述

​ 此时我们根据题目需要考虑地三个问题。

  1. 子序列里面是什么
  2. 终止位置如何去移动。
  3. 起始位置如何去移动。

子序列里面就是滑动窗口。也就是目前相加与taget比较的数组。

终止位置由动画表现可知,终止位置是遍历数组的指针。

起始位置当窗口中的值大于等于taget时,我们就向后移动一位,并且如果依然符合要求,则继续移动。

代码如下:

    public static int minSubArrayLen(int target, int[] nums) {
        int left = 0;//起始位置
        int sum = 0;//窗口数组和
        int L =Integer.MAX_VALUE;//最小子数组长度,默认为最大。
        for (int right =0;right<nums.length;right++){//终止位置,遍历数组
            sum+=nums[right];
            while (sum>=target){//这里使用while不使用if 因为如果一直符合要求的话为了获取最小子数组长度,需要继续移动。
                L =Math.min(L,right-left+1);
                sum-=nums[left];
                left++;
            }
        }
        return L==Integer.MAX_VALUE?0:L;
    }

再来两题

904. 水果成篮 - 力扣(LeetCode)

你正在探访一家农场,农场从左到右种植了一排果树。这些树用一个整数数组 fruits 表示,其中 fruits[i] 是第 i 棵树上的水果 种类 。

你想要尽可能多地收集水果。然而,农场的主人设定了一些严格的规矩,你必须按照要求采摘水果:

你只有 两个 篮子,并且每个篮子只能装 单一类型 的水果。每个篮子能够装的水果总量没有限制。
你可以选择任意一棵树开始采摘,你必须从 每棵 树(包括开始采摘的树)上 恰好摘一个水果 。采摘的水果应当符合篮子中的水果类型。每采摘一次,你将会向右移动到下一棵树,并继续采摘。
一旦你走到某棵树前,但水果不符合篮子的水果类型,那么就必须停止采摘。
给你一个整数数组 fruits ,返回你可以收集的水果的 最大 数目。

    public static int totalFruit(int[] fruits) {
        int num = 0;
        int left = 0;
        Map<Integer, Integer> basket = new HashMap<Integer, Integer>();
        for (int right = 0;right<fruits.length;right++){
            basket.put(fruits[right],basket.getOrDefault(fruits[right],0)+1);
            while (basket.size()>2){
                basket.put(fruits[left],basket.getOrDefault(fruits[left],0)-1);
                if (basket.get(fruits[left])==0){
                    basket.remove(fruits[left]);
                }
                left++;
            }
            num = Math.max(num,right-left+1);
        }
        return num;
    }

螺旋矩阵II

59. 螺旋矩阵 II - 力扣(LeetCode)

给你一个正整数 n ,生成一个包含 1n2 所有元素,且元素按顺时针顺序螺旋排列的 n x n 正方形矩阵 matrix

根据之前二分法的区间原则我们按照左闭右开的原则可以画出。

在这里插入图片描述

每一条不同的颜色代表着不同分向的遍历。

代码如下

    public static int[][] generateMatrix(int n) {
        int loop=n/2;//循环的次数
        int[][] nums = new int[n][n];//定义一个二维数组
        int start = 0;//设置每一圈的起始位置
        int offset = 1;//设置每一次遍历的长度
        int count = 1;//给数组赋值
        int i,j;

        while (loop!=0){
            //模拟左到右
            for (j=start;j<n-offset;j++){
                nums[start][j]=count++;
            }
            //模拟上到下
            for (i=start;i<n-offset;i++){
                nums[i][j]=count++;//此时j为固定值为n-offset
            }
            //模拟右到左
            for (;j>start;j--){
                nums[i][j]=count++;//此时i为固定值为n-offset
            }
            //模拟上到下
            for (;i>start;i--){
                nums[i][j]=count++;//此时j为固定值为start
            }
            start++;
            offset++;
            loop--;
        }
        //如果n为奇数则单独给中间赋值
        if (n%2==1){
            nums[start][start] = count;
        }
        return nums;
     }

数组总结

经过这两天的学习,我发现数组的并没有相信中的那么简单。其中我们了解到了。

​ 二分法。是一种对有序不重复的数组,时间复杂度:O(logn)的解法。主要掌握的是循环不变量原则。考察对区间的划分。左闭右闭和左闭右开。

​ 双指针法(快慢指针)。用来删除元素 双指针时间复杂度:O(n)的算法。通过通过一个快指针和慢指针在一个for循环下完成两个for循环的工作。

​ 滑动窗口。滑动窗口时间复杂度:O(n)。滑动窗口的精妙之处在于根据当前子序列和大小的情况,不断调节子序列的起始位置。

​ 模拟行为。通过单纯的模拟来解决问题。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

还是选择了面包

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值