IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 数据结构与算法 -> 代码随想录算法训练营第三期day02-数组02 -> 正文阅读

[数据结构与算法]代码随想录算法训练营第三期day02-数组02

一、T977:有序数组的平方

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

暴力法:

    import java.util.Arrays;//在力扣里导不导包都行,class略

    public int[] sortedSquares(int[] nums) {
        for (int i = 0; i < nums.length; ++i) {
            nums[i] *= nums[i];
        }
        Arrays.sort(nums);//没学过快速排序的话,该操作的时间复杂度无法推算
        return nums;
    }

暴力解法的时间复杂度是 O(n + nlogn), 可以说是O(nlogn)的时间复杂度

双指针法

  • 因为数组其实是有序的, 只不过负数平方之后可能成为最大数了。

    • 那数组平方的最大值一定就在数组的两端,不是最左边就是最右边,不可能是中间。

    • 此时可以考虑双指针法了,一个指向起始位置,另一个指向终止位置。

    public int[] sortedSquares(int[] nums) {
        int left = 0, right = nums.length - 1 ,k = right;
        int[] arr = new int[nums.length];
//        while (left < right) {
//如果用上面这行,逻辑上感觉是有疏漏的,不过IDEA可以输出正确结果,但在力扣会显示解答错误 
        while (left <= right) {
            if(nums[left] * nums[left] >= nums[right] * nums[right]) {
                arr[k] = nums[left] * nums[left];
                ++left;
            } else {
                arr[k] = nums[right] * nums[right];
                --right;
            }
            --k;
        }
        return arr;
    }

此时的时间复杂度为O(n),相对于暴力排序的解法O(n + nlog n)还是提升不少的。

不过空间复杂度似乎有所增加(毕竟不是原地修改数组)

二、T209:长度最小的子数组

给定一个含有?n?个正整数的数组和一个正整数 target 。找出该数组中满足其和 ≥ target 的长度最小的 连续子数组?[numsl, numsl+1, ..., numsr-1, numsr] ,并返回其长度。如果不存在符合条件的子数组,返回 0 。

暴力解法略

  • 滑动窗口(双指针)法:

所谓滑动窗口,就是不断的调节子序列的起始位置和终止位置,从而得出我们要想的结果。

????????在暴力解法中,是一个for循环滑动窗口的起始位置,一个for循环为滑动窗口的终止位置,用两个for循环 完成了一个不断搜索区间的过程。

那么滑动窗口如何用一个for循环来完成这个操作呢?

????????首先要思考 如果用一个for循环,那么应该表示 滑动窗口的起始位置,还是终止位置。

如果只用一个for循环来表示 滑动窗口的起始位置,那么如何遍历剩下的终止位置?

????????此时难免再次陷入 暴力解法的怪圈。

????????所以 只用一个for循环,那么这个循环的索引,一定是表示 滑动窗口的终止位置。

看了一遍Carl介绍的C++思路后,实现如下:

    public int minSubArrayLen(int target, int[] nums) {
        if (nums == null || nums.length <= 0) return 0;

        int sum = 0, begin = 0;
        int subLength = 0, result = Integer.MAX_VALUE;
        for (int end = 0; end < nums.length; ++end) {
            sum += nums[end];
            while (sum >= target) {
                subLength = end - begin + 1;//Java中可以用Math.min取代subLength
                result = result < subLength ? result : subLength;
//                if (begin < end) {//这段判断会导致超出时间限制(有逻辑错误,导致了死循环)
//                if (begin <= end) {//改成<=,就又可以通过了,但其实没必要判断这个
                    sum -= nums[begin++];
//                }
            }
        }
        return result == Integer.MAX_VALUE ? 0 :result;
    }

?? ?如上所示,本来自己按照看过的思路复现的时候还加上了 if?(begin?<?end) 判断,但仔细想过之后,发现如果判断 begin<end,存在以下问题:

  1. 漏掉 begin == end,也就是subLength为1之后,sum就不再扣除,进而导致while循环变成死循环;

  2. 就算,改成 begin <= end,虽然逻辑上应该是没错了,但也没有必要(能来到这里begin就绝对不可能大于end)

T59:螺旋矩阵II

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

求解本题的关键依然是要坚持循环不变量原则。

  • 模拟顺时针画矩阵的过程:

    • 填充上行从左到右

    • 填充右列从上到下

    • 填充下行从右到左

    • 填充左列从下到上

由外向内一圈一圈这么画下去。

可以发现这里的边界条件非常多,在一个循环中,如此多的边界条件,如果不按照固定规则来遍历,那就是一进循环深似海,从此offer是路人。

这里一圈下来,我们要画每四条边,这四条边怎么画,每画一条边都要坚持一致的左闭右开,或者左开右闭的原则,这样这一圈才能按照统一的规则画下来。

看了Carl的C++后自己复现,主要犯了2处错误

    public int[][] generateMatrix(int n) {
        int[][] mat = new int[n][n];
        int startx = 0, starty = 0;
        int loop = n / 2, offset = 1;
        int count = 1;
        int i, j;

        while (loop > 0) {
            i = startx; j = starty;//1、Error:i = startx, j = starty;

            for (j = starty; j < n - offset; ++j) {
                mat[i][j] = count++;
            }

            for (i = startx; i < n - offset; ++i) {
                mat[i][j] = count++;
            }

            for (; j > starty; --j) {
                mat[i][j] = count++;
            }

            for (; i > startx; --i) {
                mat[i][j] = count++;
            }

            // if (n % 2 == 1) mat[n / 2][n / 2] = count;//2、写错位置!!

            ++startx; ++starty;//1、Error:++startx, ++starty;
            ++offset;
            --loop;
        }
        if (n % 2 == 1) {
            mat[n / 2][n / 2] = count;
        }
        return mat;
    }

  数据结构与算法 最新文章
【力扣106】 从中序与后续遍历序列构造二叉
leetcode 322 零钱兑换
哈希的应用:海量数据处理
动态规划|最短Hamilton路径
华为机试_HJ41 称砝码【中等】【menset】【
【C与数据结构】——寒假提高每日练习Day1
基础算法——堆排序
2023王道数据结构线性表--单链表课后习题部
LeetCode 之 反转链表的一部分
【题解】lintcode必刷50题<有效的括号序列
上一篇文章      下一篇文章      查看所有文章
加:2022-10-31 12:25:10  更:2022-10-31 12:27:44 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/25 19:35:28-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码