03 2023 档案
摘要:题目: 思路: 【0】这道题算是 剑指 Offer II 089. 房屋偷盗(198. 打家劫舍) 的变种,增加了环形的设计。 【1】动态规划的方式 代码展示: 动态规划的方式: //时间0 ms击败100% //内存38.8 MB击败72.14% class Solution { public i
阅读全文
摘要:题目: 思路: 【0】这道题吧,怎么说,算是大学了解动态规划入门的一道题吧。思路和跳台阶很像,因为当位置为N的时候,情况可以分为两种,就是N的位置选和不选,选的话,那么根据最大值的原理,必然是F(N)= x + F(N-2) ,x为N位置的值。如果不选,那么必然是因为F(N-1)> x + F(N-
阅读全文
摘要:题目: 思路: 【1】暴力枚举的方式: 【2】使用字典树优化的方式: 代码展示: 使用字典树优化的方式: //时间29 ms击败58.92% //内存43.5 MB击败52.31% //时间复杂度:O(nl+ql∣Σ∣),其中 n 是数组 dictionary 的长度,l 是数组 dictionar
阅读全文
摘要:题目: 思路: 【0】首先题目限制了O(nlogn)的时间复杂度,这个大家应该都会有印象,毕竟大部分排序算法都是这个复杂度,其次空间复杂度为O(1),也就是说,最多借助常量值的辅助变量。而归并排序基于分治算法。最容易想到的实现方式是自顶向下的递归实现,考虑到递归调用的栈空间,自顶向下归并排序的空间
阅读全文
摘要:题目: 思路: 【0】首先常规的做法必然是不符合进阶的,毕竟要满足O(log n),那么只能二分了,不过幸好的是,数组是有序的。 【1】全数组的二分查找的方式 【2】偶数下标的二分查找的方式 代码展示: 偶数下标的二分查找的方式: //时间0 ms击败100% //内存41.8 MB击败22.25%
阅读全文
摘要:题目: 思路: 【1】错误的尝试 【2】不进行排序该如何正确的处理 【3】进行排序的处理 代码展示: 进行排序的处理: //时间5 ms击败90.74% //内存44.4 MB击败16.45% //时间复杂度:O(nlogn),其中 n 为区间的数量。 //除去排序的开销,我们只需要一次线性扫描,
阅读全文
摘要:题目: 思路: 【0】这道题怎么说呢,不算难,考察的就是能不能默写快排和堆排,说直白点就是要去记,去背,要回默写,其他的没那么重要。 【1】堆排序 【2】快速排序 【3】基于哈希表的方式 代码展示: 基于哈希表的方式: //时间1 ms击败94.61% //内存41.6 MB击败53.84% cla
阅读全文
摘要:题目: 思路: 【1】暴力破解的方式 【2】哈希表的方式 【3】字典树的方式 代码展示: 字典树的方式: //时间73 ms击败96.85% //内存60.3 MB击败47.71% //时间复杂度:O(nlogC),其中 n 是数组 nums 的长度,C 是数组中的元素范围,在本题中 C<2^31
阅读全文
摘要:题目: 思路: 【1】哈希集合(这种其实更像是暴力破解的方式,通过分割字符进行比对) 【2】字典树(字典树的逻辑研究的话会发现消耗的内存空间相对更少,但是遍历逻辑两者差不多,但是耗费的时间确实天差地别,着实是需要深思的) 代码展示: 字典树优化版本: //时间10 ms击败79.14% //内存57
阅读全文
摘要:题目: 思路: 【1】其实如果是考虑最快取出来的话,应该是对于在数组中填充对应个数的下标,如【1,3】那么对应存储的数组应该是【0,1,1,1】,这种通过随机数获取下标是最快能拿出来的,但是弊端也很明显,需要的空间很大,就如【100,500,1】,这种如果导致内存溢出。所以需要换种方式。 【2】前缀
阅读全文
摘要:题目: 思路: 【1】暴力破解的方式: 【2】桶计数+滑动窗口的方式: 利用桶排序的思想解决: 按照元素的大小进行分桶,维护一个滑动窗口内的元素对应的元素。 对于元素 xxx,其影响的区间为 [x−t,x+t]。于是可以设定桶的大小为 t+1。 如果两个元素同属一个桶,那么这两个元素必然符合条件。
阅读全文
摘要:题目: 思路: 【1】暴力破解的方式: 【2】二分查找的方式: 代码展示: 二分查找的方式: //时间24 ms击败73.28% //内存42.3 MB击败55.84% //时间复杂度:O(nlogn), 其中 n 表示日程安排的数量。由于每次在进行预订时,都需要进行二分查找,需要的时间为 O(l
阅读全文
摘要:题目: 思路: 【1】其实我觉得吧,这个题有点问题,说是必须优于O(n log n),那么是不是就是禁止使用堆了呢,优先队列里面使用的不就是堆排序的思想?那么时间复杂度也为O(n log n),这不就是禁止使用了。神神叨叨不干人事 代码展示: //时间12 ms击败89.10% //内存44.3 M
阅读全文
摘要:题目: 思路: 【0】仔细认真观察其实就会发现一个规律,这个二叉搜索树的中序遍历是顺序的,而变更之后的更大和树的中序遍历,其实就是二叉搜索树中序遍历后,从后面往前面叠加的情况,如【0,1,2,3,4,5,6,7,8】变为【36,36,35,33,30,26,21,15,8】即 7+8 = 15 ,6
阅读全文
摘要:题目: 思路: 【1】中序遍历 【2】利用二叉搜索树的性质 代码展示: 利用二叉搜索树的性质的方式: //时间2 ms击败100% //内存42.2 MB击败74.85% //时间复杂度:O(n),其中 n 是二叉搜索树的节点数。遍历的节点数不超过二叉搜索树的高度,平均情况是 O(logn),最坏
阅读全文
摘要:题目: 思路: 【1】这种情况其实递归的写法会比循环遍历的写法要好写的多,如每下一层就会把,之前的数值乘10,但同样要记住,当左右节点都为空的时候其实就不应该再往下叠一层。 代码展示: //时间0 ms击败100% //内存39 MB击败67.82% /** * Definition for a b
阅读全文
摘要:题目: 思路: 【1】递归的方式 【2】循环的方式 代码展示: 递归的方式: //时间0 ms击败100% //内存41.1 MB击败41.2% //时间复杂度:O(n),其中 n 是二叉树的节点数目。需要遍历 n 个节点。 //空间复杂度:O(n)。递归栈需要占用 O(n) 的空间。 class
阅读全文
摘要:题目: 思路: 【1】这题重点在于理解题目,首先所谓的行星只是形容,它们所处的环境不是一个圆,而是在一个平行的坐标轴上,那么对于负数是向坐标轴的左边走,正数是向右边走,而他们的下标可以看做是位置在坐标轴上的起始位置。这么说完,大概有一个整体的思路,那么要发生碰撞,必然要先有一个往右边走的正数,然后右
阅读全文
摘要:题目: 思路: 【1】利用递归的方式(在这种情况下其实递归比其他操作都要简单,当然广度也是可以做的,不过遍历次数需要两倍,如先取出来存入数组中,然后再倒序的方式进行删除) 代码展示: 简化: //时间0 ms击败100% //内存38.9 MB击败84.18% class Solution { pu
阅读全文
摘要:题目: 思路: 【0】满二叉树和完全二叉树的理念 满二叉树 ①所有叶子节点都在最后一层 ②所有分支节点都有两个孩子 完全二叉树 ①前n-1层为满的 ②最后一层不满,但最后一层从左往右是连续的 实际上若是用数组来表示 [1,2,3,4,5,6,7,8] 那么当要插入9的时候如何找到9的父节点 已知[1
阅读全文
摘要:题目: 思路: 【0】相当于层次遍历,在对每层进行遍历的时候比较拿出最右边的值(可以参考 剑指 Offer II 044. 二叉树每层的最大值(515. 在每个树行中找最大值)) 【1】广度优先搜索(使用队列的方式,这种方式的其实改动的代码不多) 【2】深度优先搜索(使用递归的方式) 代码展示: 深
阅读全文
摘要:题目: 思路: 【0】相当于层次遍历,在对每层进行遍历的时候比较拿出最大值 【1】广度优先搜索(使用队列的方式) 【2】深度优先搜索(使用递归的方式) 代码展示: 深度优先搜索: //时间0 ms击败100% //内存41.9 MB击败23.46% //时间复杂度:O(n),其中 n 为二叉树节点个
阅读全文
摘要:题目: 逆波兰表达式: 逆波兰表达式是一种后缀表达式,所谓后缀就是指算符写在后面。 平常使用的算式则是一种中缀表达式,如 ( 1 + 2 ) * ( 3 + 4 ) 。 该算式的逆波兰表达式写法为 ( ( 1 2 + ) ( 3 4 + ) * ) 。 逆波兰表达式主要有以下两个优点: 去掉括号后表
阅读全文
摘要:题目: 思路: 【1】动态规划的方式 代码展示: 动态规划的方式: //时间86 ms击败50.28% //内存50.7 MB击败30.31% //时间复杂度:O(n^2),其中 n 是数组 arr 的长度。动态规划的状态数是 O(n^2),每个状态的计算时间都是 O(1)。 //空间复杂度:O(n
阅读全文
摘要:题目: 思路: 【1】利用最大队列的思想(参考 面试题59 - II. 队列的最大值 ) 【2】单调栈的思路(与上面利用队列最大值的思路差不多): 原理分析: 对于温度列表 [73,74,75,71,69,72,76,73],单调栈 stack 的初始状态为空,答案 ans 的初始状态是 [0,0,
阅读全文
摘要:题目: 思路: 【1】动态规划的方式 【2】递归的方式(深度搜索) 代码展示: 动态规划的方式: 【1】标准的耗费空间为M*N的方式: //时间0 ms击败100% //内存39.5 MB击败77.63% //时间复杂度:O(M * N) //空间复杂度:O(M * N) //标准动态规划的方式 c
阅读全文
摘要:题目: 思路: 【1】动态规划的方式 【2】使用深度优先的方式 代码展示: 动态规划的方式: //时间2 ms击败94.62% //内存44 MB击败53.97% //时间复杂度:O(mn),其中 m 和 n 分别是网格的行数和列数。需要对整个网格遍历一次,计算 dp 的每个元素的值。 //空间复杂
阅读全文
摘要:题目: 思路: 【1】利用递归的方式: 递归的原理: 递归本质上就是拆分,你也可以想象成树一样 如s1 = "aabcc", s2 = "dbbca", s3 = "aadbbcbcac" 本质上aad这部分是没有异议的,毕竟只有他们匹配 那么剩下的便会是s1 = "bcc", s2 = "bbca
阅读全文
摘要:题目: 思路: 【0】用例展示 text1 = "ezupkr" text2 = "ubmrapg" 预期结果 2 //这种共同拥有的字母为 urp 和 upr 。 【1】动态规划的方式 代码展示: 当然在动态规划前的时候也尝试了下看看时间复杂度能不能O(n),然后发现貌似最后还是要处理那一堆乱序的
阅读全文
摘要:题目: 思路: 【1】动态规划的方式 【2】前缀和的方式 代码展示: 前缀和的方式: //时间16 ms击败36.61% //内存42.2 MB击败47.49% //本身就是利用了:最终的字符串左边全 0 右边全1的特性 //(假设到了某个点,该点不反转,将左边的全部置为0,与右边全部置为1) //
阅读全文
摘要:题目: 思路: 【1】暴力破解的方式 【2】前缀哈希映射的方式(这种方式和ES的原理有点相似,就是进行分词,每一个分词都叠加上对应的数据) 【3】字典树的方式 直接在前缀对应的 Trie 的每个节点存储该前缀对应的值: 1)insert 操作:原理与前缀哈希映射一样,我们首先求出前缀对应的值的改变
阅读全文
摘要:题目: 思路: 【1】先排序在进行相减获取最小差值,注意点:首先时钟是一个环,00:00和24:00是同一个时间,其次数字个数一共就24*60=1440个,所以超出了这个个数就必然会有重复的,也就是差值为0. 【2】使用哈希表计数的方式 代码展示: 使用哈希表计数的方式: //时间4 ms击败70.
阅读全文
摘要:题目: 思路: 【1】本质上的思路是采用二分查找 代码展示: 标准的二分查找的方式: //时间6 ms击败99.29% //内存42.5 MB击败28.75% class Solution { public int minEatingSpeed(int[] piles, int h) { int l
阅读全文
摘要:题目: 思路: 【1】利用辅助空间的方式:先遍历一遍链表,将所有节点都存于数组中,然后按顺序一头一尾的配对连起来即可。 【2】不利用辅助空间的方式:先找出中位节点,拆分成两条链表(由于是链表,所以将指针指向一断就分成两条了,保留后半部分的首节点能拿到即可),将后半部分进行反转,再将两者合并。 代码展
阅读全文
摘要:题目: 思路: 【1】利用递归的方式: 【2】利用遍历迭代的方式: 代码展示: 利用遍历迭代的方式: // 1)使用辅助空间 ,使用辅助空间的目的是为了当遇到存在分支路线的时候,将主支的下一个节点保留 // 方便等分支处理完了后还能回到主支。 //时间0 ms击败100% //内存39.4 MB击败
阅读全文
摘要:题目: 思路: 【1】注意点:返回的要是一个环状的链表 代码展示: //时间0 ms击败100% //内存40.8 MB击败65.17% //时间复杂度:O(n),其中 n 是链表的节点数。需要遍历链表一次寻找插入节点的位置,插入节点的时间是 O(1)。 //空间复杂度:O(1) /* // Def
阅读全文
摘要:题目: 思路: 【1】本质上就是利用数据结构组合,合理的达成目标,思路大致都一样,着重看的是影响速度和内存的消耗。 代码展示: //时间21 ms击败86.7% //内存90.2 MB击败54.59% class RandomizedSet { private List<Integer> list;
阅读全文
摘要:题目: 思路: 【1】动态规划的方式 动态规划的原理,如ababa为例 二维数组的情况大致是这样: [ a , b , a , b , a a:[true, false, true, false, true], b:[false, true, false, true, false], a:[fals
阅读全文
摘要:题目: 思路: 【1】剑指 Offer II 025. 链表中的两数相加(445. 两数相加 II【进阶版本】) 【1.1】链表相加,反转链表之后再相加其实是最为靠谱的 【1.2】基于进阶说不给反转,那么要么采用递归,从底层往上走。(要么就是全部取出值来形成字符串相加) 【2】2. 两数相加 代码展
阅读全文
摘要:题目: 思路: 【1】只能说这道题和 【剑指 Offer II 015. 字符串中的所有变位词(438. 找到字符串中所有字母异位词)】是一样的,逻辑都不用改,就该一下参数和返回值就可以了 【2】本质思路:利用滑动窗口加字符集数组的思想 【3】双指针的思路 代码展示: 双指针的思路: //时间2 m
阅读全文
摘要:题目: 思路: 【1】利用滑动窗口加字符集数组的思想(还有官方的题解真鸡儿复杂,感觉一样的思路,看到些那么多就没有看下去了) 代码展示: 利用滑动窗口加字符集数组的思想的方式: //时间7 ms击败75.57% //内存42.2 MB击败95.1% class Solution { public L
阅读全文
摘要:题目: 思路: 【1】基于暴力方式,采用双循环的方式【其实可以看做双指针】加上辅助记录空间,但是由于遍历是次方数的所以,其实效率感觉会比较低下,而且每一次遍历都需要开一个辅助空间,所以空间复杂度也高。 【2】进行了一波优化:采用队列的辅助空间,且只遍历一次,没遇到相同的就直接塞入队列,遇到相同的就将
阅读全文
摘要:题目: 思路: 【1】基于暴力的思想 【2】基于数据集的思想(基于 303. 区域和检索 - 数组不可变 这道题) 代码展示: 基于暴力的思想(这种是不进行初始化,而是用到了就进行遍历,虽然节约空间(也不是很大),但是如果次数多,就会发现需要的时间是基于数据集思想的数十乃至上百倍): //时间141
阅读全文
摘要:题目: 思路: 【1】利用左右汇总数据集的方式(当然做完后你会发现单个数据集其实也是可以的,毕竟一开始我以为是乘积) 代码展示: 对数据集的优化: //时间7 ms击败100% //内存44.1 MB击败75.81% class NumArray { private int[] sums; publ
阅读全文
摘要:题目: 思路: 【1】原本打算用双指针做个滑动窗口的,但是发现左指针的移动判断满是不好搞 【2】但是发现好像滑动窗口有点感觉的,但是解不出来用 前缀和 + 哈希表 貌似又能解 示例说明: //输入示例[0,0,1,0,0,0,1,1] //一开始边构建hash , [k=0 v=-1] //当下标为
阅读全文
摘要:题目: 思路: 【1】滑动窗口的双指针版本 代码展示: 双指针的方式: //时间4 ms击败100% //内存47.6 MB击败94.45% //时间复杂度:O(n),其中 n 是数组 nums 的长度。两个端点 left 和 right 的增加次数都不超过 n。 //空间复杂度:O(1)。 cla
阅读全文
摘要:题目: 思路: 【1】暴力破解,双循环遍历列举; 【2】前缀和 + 哈希表优化 这种解法是依据题目中的 连续子数组 这个条件 假设 b位置到a位置 的汇总和是符合条件的(b > a) 那么必然有 ( 0-b的汇总和) - (0-a的汇总和)= k 依据这种我们只需要知道差值的汇总和有多少个那么该位置
阅读全文
摘要:题目: 思路: 【1】貌似双循环是避不开,所以考虑的就是怎么进行快速比对,最优的就是在固定条件下用最少的空间辅助比对。 代码展示: //时间10 ms击败91.21% //内存42.2 MB击败94.62% class Solution { public int maxProduct(String[
阅读全文
摘要:题目: 思路: 【1】利用队列+单次遍历整个数组的方式来处理(这种就是模仿滑动窗口的思维) 首先要了解到本质: 因为需要知道 nums 中是否有 连续子数组 (这个要求很重点,是做窗口的前提) 能够使元素的汇总sum >= target 所以可以利用窗口的思维 而这个窗口,你可以理解为算是另一个存储
阅读全文
摘要:题目: 思路: 【1】从哈希表的角度入手:本质上这道题考察的就是检验两个字符串的字符是否相等,那么对应字符都是有编码的,根据编码为下标,s串中出现就是加,t串中出现就是减,如果字符是相等的,那么结果必然还是会是0,如果不等那么两个字符串的字符不相等(此外长度不一样一定不相等)。 【2】当然捞一点就是
阅读全文
摘要:题目: 思路: 【1】使用快慢指针找出中间,进行反转后再比较的方式(因为如果复原的话,是需要考虑后面还会不会用,其实不会用的话不复原都是可以的,毕竟好多都是直接在上面空间进行修改来节省空间) 【2】将值复制到数组中后用双指针法(这种就类似于处理回文字符串了) 【3】使用递归的方式 代码展示: 使用递
阅读全文
摘要:题目: 思路: 【1】使用辅助空间是我们最容易的想到的处理方式,先遍历一遍存起来,然后反转连起来(但明显不是最优的)。 【2】循环中不使用辅助空间的情况 需要定义两个指针,一个是tem临时存储,一个是pre头部节点的存储,加上本身的head(给予的树头节点) 如树为【5,4,3,2,1】 那么第一次
阅读全文
摘要:题目: 思路: 【1】首先这个里面需要记录最大容量,其次塞数据的存储可以考虑队列。那么如果数据超过最大容量就会从队列将前边的数据弹出,而每次平均数将是 队列里面数据的和 / 队列里面数据的个数。 【2】然后可以优化的点 代码展示: 优化代码(利用数组的环思维替代队列,可以减少开辟的空间,其次对数组的
阅读全文
摘要:题目: 思路: 【1】利用队列的形式 【2】快慢指针的思路(但这个思路局限于对场景的限制,首先限制了ping调用最多一万次,所以固定了填充的数组大小,如果没有限制呢,大体又是队列的模式了,或者环状也可以) //C++版本 class RecentCounter { public: array<int
阅读全文
摘要:题目: 思路: 【1】用优先队列实现堆的形式 代码展示: //时间15 ms击败19.10% //内存45.6 MB击败46.16% public class KthLargest { PriorityQueue<Integer> pq; int k; public KthLargest(int k
阅读全文
摘要:题目: 思路: 【1】思路1:对于树优先是遍历完全部,把数值拿出来(如中序遍历,形成数组后采用双指针就可以了判断了)。 【2】思路2:对于树优先是在遍历过程中,遍历的要存起来,且要判断差值是否已经存在了。 代码展示: 思路1的方式: //时间2 ms击败95.45% //内存42 MB击败46.20
阅读全文
摘要:题目: 思路: 【1】直接二分查找 代码展示: //时间0 ms击败100% //内存40.9 MB击败74.5% class Solution { public int searchInsert(int[] nums, int target) { int n = nums.length; int
阅读全文
摘要:题目: 思路: 【1】其实也没什么好思考的,题目给的数组就是山脉数组,可以理解为是有序的,其次,提示的复杂度就是叫你如何用二分去处理有序数组。 代码展示: //时间复杂度O(N)的方式 //时间0 ms击败100% //内存41.6 MB击败67.49% class Solution { publi
阅读全文
摘要:题目: 思路: 【1】个人理解: 体力值 10 15 20 水平线 0 1 2 天台 1.也就是说天台其实算是数组溢出一位来着。 2.可以选择0或者1位索引的阶梯为初始阶梯 3.一次最多可以跨两步,而且花费的体力为离开该位置的体力,如无论从0到1,还是从0到2,所花费的体力都是arr【0】 【2】模
阅读全文
摘要:题目: 思路: 【1】话不多说这道题本身暴力破解是可以过的,而且基于限制为Integer.MAX_VALUE,所以可以知道根号为46341,那么基于这个进行遍历就好了。 【2】基于二分进行优化,因为从暴力破解这里我们看到了,不一定需要遍历那么多数据,所以筛选数据快的方式不就是二分吗,一下子过掉一半的
阅读全文
摘要:题目: 思路: 【1】其实最简单的便是计数排序,先将全部按照map进行映射,然后根据第二个数组的顺序先塞,最后的把剩下的再塞进去。 【2】当然还有一种自定义排序的方式,只能说有点秀。 由于数组arr2 规定了比较顺序,因此我们可以使用哈希表对该顺序进行映射: 即对于数组 arr2 中的第 i 个元
阅读全文
摘要:题目: 思路: 【1】基于回文字符串的思维,采用双指针,如果字符相同就两个都移动,那么如果不同呢,那么就是要才去其中一个去除掉。其实用递归比较合适,只要设置一个标志位就可以了(可以考虑int类型),哈哈,如果变化成删除多个,就改一下标志位。 代码展示: 基于回文字符串思维的方式: //时间4 ms击
阅读全文