![](https://img-blog.csdnimg.cn/20190918140129601.png?x-oss-process=image/resize,m_fixed,h_224,w_224)
数据结构与算法
文章平均质量分 65
1
姜大师在线求学
这个作者很懒,什么都没留下…
展开
-
二叉树的层序遍历
1二叉树的层序遍历层序遍历一个二叉树。就是从左到右一层一层的去遍历二叉树。这种遍历的方式和我们之前讲过的都不太一样。需要借用一个辅助数据结构即队列来实现,队列先进先出,符合一层一层遍历的逻辑,而是用栈先进后出适合模拟深度优先遍历也就是递归的逻辑。而这种层序遍历方式就是图论中的广度优先遍历,只不过我们应用在二叉树上。使用队列实现二叉树广度优先遍历,动画如下:代码实现如下: //二叉树的层次遍历 public static class Solution3{原创 2022-05-20 16:05:57 · 625 阅读 · 0 评论 -
二叉树的迭代遍历
递归的实现就是:每一次递归调用都会把函数的局部变量、参数值和返回地址等压入调用栈中,然后递归返回的时候,从栈顶弹出上一次递归的各项参数,所以这就是递归为什么可以返回上一层位置的原因。前序遍历(迭代法)我们先看一下前序遍历。前序遍历是中左右,每次先处理的是中间节点,那么先将根节点放入栈中,然后将右孩子加入栈,再加入左孩子。为什么要先加入 右孩子,再加入左孩子呢? 因为这样出栈的时候才是中左右的顺序。动画如下:所以代码如下:1节点类public class TreeNod.原创 2022-05-17 23:52:01 · 70 阅读 · 0 评论 -
二叉树的递归遍历:
这里帮助大家确定下来递归算法的三个要素。每次写递归,都按照这三要素来写,可以保证大家写出正确的递归算法! 确定递归函数的参数和返回值:确定哪些参数是递归的过程中需要处理的,那么就在递归函数里加上这个参数, 并且还要明确每次递归的返回值是什么进而确定递归函数的返回类型。 确定终止条件:写完了递归算法, 运行的时候,经常会遇到栈溢出的错误,就是没写终止条件或者终止条件写的不对,操作系统也是用一个栈的结构来保存每一层递归的信息,如果递归没有终止,操作系统的内存栈必然就会溢出。 确定单..原创 2022-05-16 21:57:15 · 87 阅读 · 0 评论 -
单调栈java算法
比如说,输入一个数组 nums = [2,1,2,4,3],你返回数组 [4,2,4,-1,-1]。解释:第一个 2 后面比 2 大的数是 4; 1 后面比 1 大的数是 2;第二个 2 后面比 2 大的数是 4; 4 后面没有比 4 大的数,填 -1;3 后面没有比 3 大的数,填 -1。这道题的暴力解法很好想到,就是对每个元素后面都进行扫描,找到第一个更大的元素就行了。但是暴力解法的时间复杂度是 O(n^2)。这个问题可以这样抽象思考:把数组的元素想象成并列站立的人,元素大小想象成人的身高。原创 2022-05-12 21:32:49 · 439 阅读 · 1 评论 -
常数时间删除/查找数组中的任意元素
1时间插入、删除和获取随机元素这些问题的一个技巧点在于,如何结合哈希表和数组,使得数组的删除操作时间复杂度也变成 O(1)?下面来一道道看。代码如下:class RandomizedSet { List<Integer> list=new ArrayList<>(); Map<Integer,Integer> map= new HashMap<>(); Random random= ne.原创 2022-05-11 20:27:15 · 267 阅读 · 0 评论 -
带权重的随机选择算法和田忌赛马背后的算法决策
1带权重的随机算法解法代码就比如这个 preSum 数组,你觉得随机数 target 应该在什么范围取值?闭区间 [0, 7] 还是左闭右开 [0, 7)?都不是,应该在闭区间 [1, 7] 中选择,因为前缀和数组中 0 本质上是个占位符,仔细体会一下:int n = preSum.length;// target 取值范围是闭区间 [1, preSum[n - 1]]int target = rand.nextInt(preSum[n - 1]) + 1;接下.原创 2022-05-10 22:02:12 · 183 阅读 · 0 评论 -
二分搜索的学习
一、寻找一个数(基本的二分搜索)这个场景是最简单的,可能也是大家最熟悉的,即搜索一个数,如果存在,返回其索引,否则返回 -1框架代码:int binarySearch(int[] nums, int target) { int left = 0; int right = nums.length - 1; // 注意 while(left <= right) { int mid = left + (right - left) / 2;原创 2022-05-09 20:49:09 · 66 阅读 · 0 评论 -
滑动窗口算法举一反三
本题思路:我们在字符串S中使用双指针中的左右指针技巧,初始化left = right = 0,把索引左闭右开区间[left, right)称为一个「窗口」。PS:理论上你可以设计两端都开或者两端都闭的区间,但设计为左闭右开区间是最方便处理的。因为这样初始化left = right = 0时区间[0, 0)中没有元素,但只要让right向右移动(扩大)一位,区间[0, 1)就包含一个元素0了。如果你设置为两端都开的区间,那么让right向右移动一位后开区间(...原创 2022-05-05 22:12:55 · 143 阅读 · 0 评论 -
遍历二维数组的一些技巧
顺/逆时针旋转矩阵题目很好理解,就是让你将一个二维矩阵顺时针旋转 90 度,难点在于要「原地」修改,函数签名如下void rotate(int[][] matrix)如何「原地」旋转二维矩阵?稍想一下,感觉操作起来非常复杂,可能要设置巧妙的算法机制来「一圈一圈」旋转矩阵:但实际上,这道题不能走寻常路,在讲巧妙解法之前,我们先看另一道谷歌曾经考过的算法题热热身:给你一个包含若干单词和空格的字符串s,请你写一个算法,原地反转所有单词的顺序。比如说,给你输入这样一个字符串:...原创 2022-04-27 21:12:04 · 1320 阅读 · 1 评论 -
差分数组的应用
一个和前缀和思想非常类似的算法技巧「差分数组」,差分数组的主要适用场景是频繁对原始数组的某个区间的元素进行增减。比如说,我给你输入一个数组 nums,然后又要求给区间 nums[2..6] 全部加 1,再给 nums[3..9] 全部减 3,再给 nums[0..4] 全部加 2,再给…一通操作猛如虎,然后问你,最后 nums 数组的值是什么?常规的思路很容易,你让我给区间 nums[i..j] 加上 val,那我就一个 for 循环给它们都加上呗,还能咋样?这种思路的时间复杂度是 O(N),由原创 2022-04-26 20:56:39 · 381 阅读 · 0 评论 -
前缀和数组
一维数组中的前缀和这道题的最优解法是使用前缀和技巧,将sumRange函数的时间复杂度降为O(1),说白了就是不要在sumRange里面用 for 循环核心代码如下class NumArray { // 前缀和数组 private int[] preSum; /* 输入一个数组,构造前缀和 */ public NumArray(int[] nums) { // preSum[0] = 0,便于计算累加和 preSum...原创 2022-04-25 21:32:35 · 145 阅读 · 0 评论 -
如何判断回文链表
题目如下解题思路:首先我们找到该链表的中点节点ListNode slow, fast;slow = fast = head;while (fast != null && fast.next != null) { slow = slow.next; fast = fast.next.next;}// slow 指针现在指向链表中点如果fast指针没有指向null,说明链表长度为奇数,slow还要再前进一步if (fast != nul.原创 2022-04-22 21:54:21 · 333 阅读 · 0 评论 -
如何 K 个一组反转链表
思路:这个问题经常在面经中看到,而且力扣上难度是 Hard,它真的有那么难吗?对于基本数据结构的算法问题其实都不难,只要结合特点一点点拆解分析,一般都没啥难点。下面我们就来拆解一下这个问题。一、分析问题首先,前文学习数据结构的框架思维提到过,链表是一种兼具递归和迭代性质的数据结构,认真思考一下可以发现这个问题具有递归性质。什么叫递归性质?直接上图理解,比如说我们对这个链表调用reverseKGroup(head, 2),即以 2 个节点为一组反转链表:如果我设法把前...原创 2022-04-22 21:44:20 · 2127 阅读 · 0 评论 -
递归反转链表的一部分
什么叫反转单链表的一部分呢,就是给你一个索引区间,让你把单链表中这部分元素反转,其他部分不变注意这里的索引是从 1 开始的。迭代的思路大概是:先用一个 for 循环找到第 m 个位置,然后再用一个 for 循环将 m 和 n 之间的元素反转。但是我们的递归解法不用一个 for 循环,纯递归实现反转。迭代实现思路看起来虽然简单,但是细节问题很多的,反而不容易写对。相反,递归实现就很简洁优美,下面就由浅入深,先从反转整个单链表说起。一、递归反转整个链表这也是力扣第 206 题「反转链表.原创 2022-04-20 21:43:21 · 287 阅读 · 0 评论 -
双指针技巧2
单链表的中点力扣第 876 题「链表的中间结点」就是这个题目,问题的关键也在于我们无法直接得到单链表的长度n,常规方法也是先遍历链表计算n,再遍历一次得到第n / 2个节点,也就是中间节点。如果想一次遍历就得到中间节点,也需要耍点小聪明,使用「快慢指针」的技巧:我们让两个指针 slow 和 fast 分别指向链表头结点 head。每当慢指针 slow 前进一步,快指针 fast 就前进两步,这样,当 fast 走到链表末尾时,slow 就指向了链表中点。上述思路的代码实现如...原创 2022-04-14 23:41:36 · 204 阅读 · 0 评论 -
双指针技巧1
合并两个有序链表:给你输入两个有序链表,请你把他俩合并成一个新的有序链表:核心代码如下:public class ListNode { int val; ListNode next; ListNode() {} ListNode(int val) { this.val = val; } ListNode(int val, ListNode next) { this.val = val; this.next =.原创 2022-04-13 21:55:36 · 718 阅读 · 0 评论 -
螺旋矩阵和长度最小的子数组的算法
给你一个正整数 n ,生成一个包含 1 到 n2 所有元素,且元素按顺时针顺序螺旋排列的 n x n 正方形矩阵 matrix如图:代码如下: public static void main(String[] args) { Solution solution = new Solution(); int[][] ints = solution.generateMatrix(1); System.out.println(Arrays.deepTo.原创 2022-03-10 21:22:32 · 97 阅读 · 0 评论 -
二分查找与数组移除元素的算法
二分查找的做法是,定义查找的范围[left,right],初始查找范围是整个数组。每次取查找范围的中点 mid,比较 nums[mid] 和 target 的大小,如果相等则mid 即为要寻找的下标,如果不相等则根据 nums[mid] 和target 的大小关系将查找范围缩小一半。public class Demo3 { public static void main(String[] args) { Solution solution = new Solution();原创 2022-03-07 22:21:57 · 195 阅读 · 0 评论 -
java数据结构
一维数组:对区间的合并public class demo { public static void main(String[] args) { int [][] intervals = {{1,3},{2,6},{15,18},{8,10}}; Solution solution = new Solution(); int[][] merge = solution.merge(intervals); System.out.pri原创 2022-02-24 22:56:55 · 524 阅读 · 0 评论