自定义博客皮肤VIP专享

*博客头图:

格式为PNG、JPG,宽度*高度大于1920*100像素,不超过2MB,主视觉建议放在右侧,请参照线上博客头图

请上传大于1920*100像素的图片!

博客底图:

图片格式为PNG、JPG,不超过1MB,可上下左右平铺至整个背景

栏目图:

图片格式为PNG、JPG,图片宽度*高度为300*38像素,不超过0.5MB

主标题颜色:

RGB颜色,例如:#AFAFAF

Hover:

RGB颜色,例如:#AFAFAF

副标题颜色:

RGB颜色,例如:#AFAFAF

自定义博客皮肤

-+
  • 博客(39)
  • 收藏
  • 关注

原创 Thinking in JAVA:类型信息(1)

RTTI:运行时的对象类型信息识别,大方向可以分为两种最传统的RTTI就是静态识别,程序编译之后,编译器就知道该对象的类型信息运行时识别,需要用到反射机制Class对象每个类都拥有一个Class对象,这个Class对象会被存储到与类名相同的.class文件里面为了生成某个类的对象,JVM将使用其中的类加载器类加载器首先检查对应类的Class对象是否已经加载,如果没有,默认的加载器就会根据类名查找.class文件(字节码)。当Class对象被加载到内存的时候,就会被用来创建这个类的

2020-05-31 23:59:51 117

原创 Thinking in java: 通过异常来处理错误(1)

抛出异常的作用通过规定某种必须保证的形式来防止随心所欲的编程导致的问题,降低处理代码错误的复杂度。异常是对一种“知道这么做不对,但是代码无法立马解决的”情况的描述异常将每件事都当做一个事务,作为每个事务的底线维护它们的逻辑稳定性。一旦异常发生,就不允许程序按照正常模式执行下去。基本异常使用throw 抛出异常对象的引用,异常对象的名字一般以Exception结尾抛出异常之后,会发生什么?使用new在堆上创建异常对象停止当前执行路径,抛出异常对象的引用异常机制接管程序,在异常处理程

2020-05-31 14:18:06 248

原创 Leetcode 101: 对称二叉树(非正常顺序BFS)

题解题意:给定一个二叉树,检查是否对称。题解:首先,直观上,二叉树对称就是将二叉树根据根节点对折之后,左右子树能否完全重合,想要左右子树完全重合,就是要左子树的左儿子等于右子树的右儿子,且左子树的右儿子等于右子树的左儿子,因此递归比较好写,就是针对左右子树的孩子节点进行一个dfs即可。不过这里有一个比较特殊的情况,就是既然是关于根节点镜像对称,根节点的左右儿子也必须相等,不过有意思的是,把root节点既当作左树,又当作右树,那么判断上面的条件,就等于判断root的左右儿子是否相等。递归版本实现

2020-05-31 13:14:41 158

原创 Thinking in java: 异常处理(2)

异常说明java强制让函数名后面接上throws+异常类型明示这个方法可能抛出的所有异常类型,比如f()中可能在某些判断体内会有TooBig, TooSmall, DivZero这些类型的异常,那么代码在实现的时候,就需要加上 void f() throws TooBig, TooSmall, DivZero{...}只有RuntimeException类型的异常是可以不显示表示的如果f()潜在一些异常,但是却没有被告知,那么f()将会被编译器提醒要检查异常可以在异常说明中写上该方法可能不

2020-05-30 16:30:52 205

原创 Leetcode 84: 柱状图中的最大矩形(扩散+单调栈)

题解题意:给定数组heights[],包含n个非负整数,用来表示柱状图中各个柱子的高度。每个柱子彼此相邻,且宽度为 1 。求在该柱状图中,能够勾勒出来的矩形的最大面积,矩形中间不能为空,样例,给定数组heights = [2,1,5,6,2,3], 输出10,即阴影部分的面积:题解:首先考虑什么情况下可能围成最高的矩形?自然是要么够宽,要么够高,但是这两个并没有依赖性,因此需要共同考虑,而暴力做法在有两个自由变量的时候,复杂度都是O(n2)O(n^2)O(n2),不合适,我们要考虑如何减少没必要的状

2020-05-30 12:31:27 308

原创 Leetcode 198, 213, 337:打劫家舍系列

题解打劫家舍 1(01背包)题意:村里的房屋成一字排列,现在给定一个数组nums里面每个数据代表对应编号房屋中的财产。有一个强盗想在这个村庄中打劫,但是如果连续打劫两家相邻的房屋,会导致系统报警,请设计一个算法,在不出动警报的情况下让强盗获取最大金额题解:很直接的01背包问题,因为要表示最大值,我们首先考虑针对每个房屋的状态表示。我们可以利用dp[i]表示第i家房屋之前,最多能够打劫多少金额,那么如果下次打劫如果用上了dp[i],就不用考虑i之前的状态了。现在考虑dp[i]是如何通过上一个状态转

2020-05-29 11:44:44 364

原创 394. 字符串解码(辅助栈+字符串栈)

题解题意:字符串的编码规则为: k[encoded_string],表示其中方括号内部的 encoded_string 正好重复 k 次。注意 k 保证为正整数。 给定一个经过编码的字符串,返回它解码后的字符串样例s = “3[a]2[bc]”, 返回 “aaabcbc”.s = “3[a2[c]]”, 返回 “accaccacc”.s = “2[abc]3[cd]ef”, 返回 “abcabccdcdcdef”.题解:无疑,越是嵌套在里面的括号,要被重复的次数就越多,一定是越里层括号

2020-05-28 12:05:33 191

原创 Think in java: 什么是java内部类(1)

内部类是什么类中定义的类(隐藏名字)仅对包含该内部类的’外部类’可见静态方法必须通过外部类.内部类的方式来调用 (是因为没有this指针?)外部类能够访问内部类的一切对象,包括private链接到外部类内部类能访问所有制造它的外围对象的成员引出设计模式之一:迭代器模式,将某个数组以类的形式包装起来,并设计诸如add(). next(), end()等方法的形式对数组进行修改与访问的操作:interface Selector{ boolean end(); Object c

2020-05-27 16:36:29 169

原创 leetcode 974:和可被k整除的子数组(同余定理+哈希记录)

题解题意:给定一个整数数组 A,返回其中元素之和可被 K 整除的(连续、非空)子数组的数目。其中k<=10000, A.length <= 10000题解:连续非空的元素之和,最容易想到的就是求前缀和,利用pre[r]-pre[l]的方式得到区间内满足条件的子数组和。然而前缀和遍历所有情况需要o(n^2)的复杂度,因此,很多情况下,包括此题,这都是不可能直接做的,因此我们需要表示状态,然后进行状态的压缩整除的状态:一般而言,只要是要求不能遍历所有数据的,都是存在一个规律使得不需要遍历所

2020-05-27 11:27:36 448

原创 leetcode 287. 寻找重复数(数组中的快慢指针)

题解题意:给定一个包含 n + 1 个整数的数组 nums,其数字都在 1 到 n 之间(包括 1 和 n),可知至少存在一个重复的整数。假设只有一个重复的整数,找出这个重复的数。要求时间复杂度是o(n)且额外空间复杂度只能是o(1)题解:在介绍此题之前,先介绍一个非常相似的题目:数组中重复的数字数组中的重复数字数组中重复的数字:一开始看错题,以为思路和这个一样。此题是利用原地桶排序的思想,因为数组中的数据范围都在(0,n-1),小于等于数组的长度,那么如果每个元素不重复,那在正常排序

2020-05-26 15:18:37 399

原创 Leetcode 146:LRU缓存机制(哈希+双向链表,终于自己写出来了没bug的版本)

题解设计和实现一个 LRU (最近最少使用) 缓存机制,(如果不懂LRU机制的,需要先学习操作系统的LRU调度算法,先从理论上知道实现方式才行),支持以下操作: 获取数据 get 和 写入数据 put ,且两个操作都需要在O(1)复杂度下完成LRU算法大意:给定一个固定大小的容器,容器中的事物代表需要使用的事物,以及一系列事物,每个事物都有自己的key, value值,其中key用来识别自身的身份,value则是内容。在容器没有满的时候,事物会不断向容器里面添加,容器满的时候,就把最早添加到容

2020-05-25 11:44:01 204

原创 Leetcode 4. 寻找两个正序数组的中位数 (数组划分+中位数位置搜索)

题解题意:给定两个大小为 m 和 n 的正序(从小到大)数组 nums1 和 nums2。请你找出这两个正序数组的中位数,并且要求算法的时间复杂度为 O(log(m + n))。题解:此题主要是找到两个数组的中位数位置,不断地在两个数组中寻找合理的分割线位置。中位数位置:(m+n)偶数:(m+n+1)/2的左右两边,m+n奇数:(m+n+1)/2所处元素。对于奇数来说,就是划分成两堆数据之后,奇数长度数组的中位数就在元素多一个的那边(如9个元素,划分成5+4,中位数就在5那一堆)在两个数组

2020-05-24 12:24:38 334

原创 Leetcode 76. 最小覆盖子串(滑动窗口+文本距离)

题解题意:给你一个字符串 S、一个字符串 T,请在字符串 S 里面找出:包含 T 所有字符的最小子串,顺序可以不一样。如果S并没有包含T的子串,那么返回"",否则,样例的S只会包含唯一的一个最短覆盖子串。T中可能包含重复字符,比如输入: S = “ADOBECODEBAANC”, T = “AABC”输出: “BAANC”题解:这题思路其实比一些中等题目简单(当然我是看题解才做出来的),查找字符串字串的题型考的最多的就是双指针滑动窗口的思路,但是这题还有一个点在于使用汉明距离来表示两个两

2020-05-23 14:49:59 242

原创 Leetcode 105:前序与中序遍历序列构造二叉树(递归+哈希提升效率)

题解题意:根据一棵树的前序遍历与中序遍历(所有节点的数值唯一)构造二叉树。如给定前序遍历 preorder = [3,9,20,15,7]中序遍历 inorder = [9,3,15,20,7]返回 3/ \9 20 / \ 15 7题解:我们知道前序遍历是根-左-右的顺序进行的,而中序遍历是左-根-右的顺序。两个遍历对确认节点的位置各有帮助,是两个工具序列其中,前序遍历用于找到根节点的位置,因为对于任何一颗子树的前序遍历,根节点都是第一个

2020-05-22 11:34:56 160

原创 leetcode 5: 最长回文子串(中心扩展算法)

题解题意: 给定一个字符串 s,找到 s 中最长的回文子串。你可以假设 s 的最大长度为 1000。题解:虽然长度是1000,但是如果暴力求每个子串的翻转来判断,那似乎是O(n^3)的复杂度,因此不可取。个人认为中心扩展算法是解决最长回文子串问题的最容易掌握的方法,这种算法时间复杂度是O(n^2),空间复杂度是O(1)(但是不是复杂度最优的算法,最优的算法是Manacher算法,时空复杂度都是O(n),但是比较复杂,需要经常看才能掌握)中心扩展算法:巧妙的利用了回文串的特点,就是从中心到两

2020-05-21 10:28:15 278

原创 leetcode 1371. 每个元音包含偶数次的最长子字符串(哈希+状态压缩表示)

题解题目:给你一个字符串 s ,请你返回满足以下条件的最长子字符串的长度:子串中包含的元音字母,即 ‘a’,‘e’,‘i’,‘o’,‘u’ ,在子字符串中都恰好出现了偶数次。(字符串长度最大是 5*10^5)题解:最简单的做法就是两重循环,遍历所有子串,但是这明显是不行的,因为数据长度限制了O(n^2)的做法。那么如何优化复杂度,官方题解给了两个方向。状态记录:使用二重前缀和pre[i][k]:保留第i个字符前面的字符串中,第k个元音字符出现的次数,这样一来,每个字符出现的次数就可以通过pre[r

2020-05-20 12:27:53 249

原创 leetcode 152: 最大乘积数组(动态规划)

题解题意:给你一个整数数组 nums ,请你找出数组中乘积最大的连续子数组(该子数组中至少包含一个数字),并返回该子数组所对应的乘积。题解:此题要求找到连续乘积最大的子数组,连续数组的意义是什么,一个最直观的想法就是,如果前面的乘积在乘了元素i之后变大了,那么就把元素i加入到子数组中,否则,则从第i项开始,再进行记录。但是这会遇到一个问题,正数如果乘以负数,那么就是变小了,此时如果抛弃掉前面的项,很明显是不对的,因为后面如果又遇到一个负数,那么最小值又变成最大值了,因此我们不能因为乘以了一个负数,

2020-05-18 11:19:58 234

原创 java可变参数列表

利用... args作为形参,如下例所示,可变参数列表可以随便接受任何类型的变量: public class NewVarArgs{ static void printArray(Object... args){ for (Object obj:args){ System.out.print(obj+" "); } System.out.println(); } } public static void main(String[] args){ printAr.

2020-05-17 23:11:34 106

原创 leetcode 210. 课程表 II(拓扑排序)

题解题目:在选修某些课程之前需要一些先修课程。 例如,想要学习课程0,你需要先完成课程1。我们用一个匹配来表示他们: [1,0]。例子,给定一个数字代表课程总量,以及n对数据,前者代表要学课程, 后者代表基础课程,4, [[1,0],[2,0],[3,1],[3,2]]。题解:拓扑排序,很简单的想法,根据需求关系建立一个有序拓扑图,首先将入度为0的点找出来,然后将相邻节点的度数减1,如果相邻节点的度数为0了,就加入到队列中,循环这个过程,直到队列是空的。class Solution {

2020-05-17 12:50:42 195

原创 leetcod 25:K个一组反转链表(思路很直接,但是处理细节较多的hard题)

题解题目:给定链表的头和整数k,k小于链表长度,要求对链表中每k个节点进行一次翻转,如示例所示题解:这题是翻转链表的拓展版。主要思路:针对每个长度为k的子链(简称k链)进行一个翻转,将前一个k链的末尾节点连接上下一个k链的开头节点。首先是如何找到k链,方法有不少,但是最实用的方法就是设置头指针和尾指针,尾指针指向第k个节点即可。找到k链之后,就是进行翻转操作,这里使用头插法,链表翻转就不多介绍了。然后就是讨论如何连接上一个k链和下一个k链的问题了。这个问题主要涉及到两个节点,一个是上一个k

2020-05-16 15:34:53 171

原创 jvm: 垃圾清理算法之CMS

并发标记清理(Concurrent Mark-Sweep)相对于之前算法的改进,之前的清理算法都需要将正在工作的线程停止,然后再调用GC,CMS出来之后,GC调用的时候,工作的线程仍然可以工作工作原理:CMS并非完全进行GC和工作线程,而是在启用GC的时候,会事先停止工作程序,找到根垃圾对象(在堆或者静态存储区上的0引用对象),找到根之后垃圾之后,恢复GC和线程的工作,此时GC再从根开始,根据引用链进行搜索。冲突:那么问题来了,如何处理GC和正在工作线程的冲突呢,比如,GC正在清理的时候,因为线程中

2020-05-15 17:53:12 188

原创 java编程思想阅读笔记:初始化与清理

初始化构造器(constructor):就是C++中的构造函数,不写也会有一个默认的无参构造函数,会给所有成员变量进行一个初始化重载:方法名字相同,但是参数不同(最开始是为了实现构造器而设置的,后来发现可以帮助多态的实现)。为什么重载不能根据返回值的不同来确定?因为存在歧义,比如void f(); int f(); 同时存在,然后主函数写了main(){f();},此时编译器无法知道这个f()指的是哪一个函数。涉及基本类型的函数重载:基本类型能够升级,比如void f(float a)可以通过f

2020-05-15 00:43:19 148

原创 leetcode :三数之和系列(排序+双指针+去重)

相关的题解leetcode 15 三数之和:给定一个数组nums,找出数组里面三个数字之和为0的组合,组合不能重复题解:先给数组排好序,然后固定最左边的数(i)。然后在右边数组中找两个数字, 看是否满足情况,此时就运用到了双指针算法。设置两个指针j,k,j指向i右边的第一个数字(j=i+1),k另一个指向数组的最后一个数字k=nums.length-1,分别代表三数中的中间值和最大值如果此时nums[i]+nums[j]+nums[k]>0说明k太大了,执行k--如果此时nums[i]

2020-05-14 18:40:11 215

原创 一种简单的记忆方法:关于二分查找upper_bound和lower_bound

一种从结果看结论的方法,好记但是不严谨上下界的区别主要是向左还是向右逼近目标值,让我们来看看是如何实现的上界 int upper_bound(int arr[], int target){ int n = sizeof(arr)/sizeof(int); int l = 0, r = n-1; while(l<r){ int mid = (l+r+1)>>1; if(arr[mid] <= target) l = mid; else r =

2020-05-14 17:44:34 401

原创 leetcode 1287: 有序数组出现次数超过25%的元素(神烦二分查找上下界)

题解题意:给定非递减整数数组arr, arr中恰好有一个整数,它的出现次数超过数组元素总数的 25%。题解:最简单的就是利用双指针设置一个0.25*arr.length大小的窗口,一位位往后遍历,这个几行代码就可以实现,O(n)。我们再看看题目,题目告诉我们,数组是排好序的,既然是因为数组是排好序的,就可以考虑二分法计数法。二分法计数是因为二分查找有两种,一种是找到重复数字第一次出现的位置,另一种是找到重复数据最后一次出现的位置,这也成为lower_bound和upper_bound查找法。这题

2020-05-13 21:46:27 254

原创 java程序建立前应该做的事

包命名管理或许大家多多少少看过一些网课,讲课的大佬们命名一个文件往往都是根据包的路径,使用采用类似域名的方式来命名的,比如com.user.util.worker,这样确保每一个文件都有属于它自己唯一的名字使用其他构件导入非当前目录与系统路径的包,使用import关键字根据类库导入一个或者多个类,如import java.util.ArrayList,import java.util.*,每个java程序的开头,都必须有import语句,便于引入额外类。static关键字修饰的方法当一个

2020-05-12 23:22:44 139

原创 leetcode 456: 132模式 (前缀最小值+单调栈)

题解题意:给定数组a1, a2, …, an,一个132模式的子序列 ai, aj, ak 被定义为:当 i < j < k 时,ai < ak < aj。 给定数组nums[],判断是否有132模式题解:此题主要是找到一个下标最大的中间值,下标最小的最小值,和下标中间的最大值。下标最小的最小值最好找,就是从前往后遍历一遍数组,第j个位置的最小值就是以j为末尾元素的前缀数组的最小值, 因此首先用一个min数组来记录到第j个数字之前出现的最小值下标最大的中间值则可以通

2020-05-12 10:33:36 375 2

原创 leetcode 50: 快速幂(非递归与递归)

题解题意:实现函数pow(x,n),其中x是double类型,n是int类型(n是)除了快速幂算法之外,还要注意int类型的正负号取值范围不一样。题解:快速幂算法(分治思想)举两个例子,求x64x^{64}x64, 和x10x^{10}x10x2=(x∗x)→x4=(x2)∗(x2)→x8=(x4)∗(x4)∗x→x16=x8∗x8→x32=x16∗x16→x64=x32∗x32x^2 = (x*x)\to x^4 = (x^2)*(x^2) \to x^8 = (x^4)*(x^4)

2020-05-11 10:29:38 230

原创 leetcode 236: 二叉树的最近公共祖先(面试常考)

题解题意:给出一个二叉树根节点root,以及两个子节点p,q,求p,q的最低公共父节点,如下图,给出节点3,节点6,7要返回5分析:什么叫做最低公共祖先?祖先:如果一个节点的左子树或者右子树包含所需要寻找的两个节点p,q,那么说明左或者右子树中包含了他们的祖先最低祖先:那么什么是最低祖先呢,有两种情况,一种情况是p就是q的祖先,那么最低祖先就是p,如果不是,那么就是当p,q分布在一个节点的左右子树的时候,就是这个节点就是最低祖先,因为无论递归左子树还是右子树都会失去一个。方法1:

2020-05-10 12:00:11 196

原创 leetcode 69: x的平方根(三种方法)

题解袖珍计算器x^1/2 = (e^lnx)^1/2 = e^(1/2lnx)转换成求lnx,感觉没有什么提升,都用了内置函数,还不如直接调用sqrt二分查找 public int mySqrt(int x) { long i = 1, j = x, ans = 0; while(i<=j){ long mid = (i+j)/2; if(mid*mid <= x) { ans

2020-05-09 11:23:16 236

原创 Redis深度历险阅读笔记(2):分布式锁

千帆竞发——分布式锁应用场景:应对并发锁的问题,多个用户的读和写并不是原子的实现:利用key+setnx(没有key才建立)操作来模拟互斥量,如setnx lockc true...del lock问题1:如果线程执行过程中间抛出异常,那么将会导致del失败,造成死锁问题对应方案1:给key设置一个过期时间,即便中途异常退出也会删除 setnx lockc true expire lockc 5问题2:这个问题比较牛角尖,但是可能会发生。因为setnx和exipre都不是原子的

2020-05-08 23:36:34 129

原创 Leetcode 221. 最大正方形(动态规划)

题解题意:在一个01矩阵matrix[][]中,找到全是1的最大正方形。题解:不难想到,(i, j)位置为右下角的正方形面积是由上一个状态的正方形决定的,因此比较容易想到是动态规划的做法,利用dp[i][j]维护位置(i,j)为右下角的正方形的边长状态 ,那么状态转换方程是什么,似乎不是很直观就可以得到,但是有一个最直观的状态,就是matrix[i][j]=0,那么dp[i][j]=0...

2020-05-08 11:47:27 208

原创 Redis深度历险笔记(1):基础数据结构篇

Redis全称:远程字典服务(Remote Dictionary Service),从名字可以看出来Redis是一个key-value形的非关系型数据库(NoSQL),貌似除了windows系统都支持应用:缓存,分布式锁,等默认端口:6379安装(centos):yum intall redis运行:redis-cli万丈高楼平地起:支持的五种数据结构类型作用...

2020-05-07 14:37:29 185

原创 leetcode 572: 另外一颗树的子树(DFS)

题解题意:给定两颗树的根节点,s,t,判断t所表示的树是不是s所表示的树的子树题解:总共三种情况,要么s树等于t树,要么s树的左子树等于t树的左子树,要么s树的右子树等于t树的右子树,如果s树遍历完了都没找到t树重合的子树,那么说明没有同样的实现,java递归效率为什么比C++高这么多?C++版本class Solution {public: bool dfs(Tre...

2020-05-07 10:08:04 181

原创 leetcode983 每日一题:最低票价(动态规划)

题解题目大意:旅游规划,给出数组days, days中的数据小于365,要求days给出的日期都能旅行,days中的日期是单调递增的。旅社有三种方案供选择,分别是1日游,7日游,30日游,三种价格记录在cost数组中,价格不一定从低到高输出:覆盖所有days的旅行最少需要多少钱题解:不难发现,每个日期的价格取决于上一次价格的开销+这次的票价,因此是动态规划问题状态转移:...

2020-05-06 11:37:22 266

原创 二叉树题目:验证搜索二叉树(leetcode 98)

中序遍历二叉搜索树的中序遍历可以形成有序数组,最暴力的做法就是将遍历的数据存储起来,再进行判断。vector<int> v; void inner(TreeNode* root ){ if(!root) return; inner(root->left); v.push_back(root->val); ...

2020-05-05 13:39:13 136

原创 古老的编码技术:哈夫曼编码

哈夫曼树过程很简单,就是迭代的将最小权值树查到原有树的上面每一步迭代都可以视为寻找权重最小的两个点,合并成一棵树将合并的树视为一个新的节点,将节点中两个权重最小的节点删除//HT数组中存放的哈夫曼树,end表示HT数组中存放结点的最终位置,s1和s2传递的是HT数组中权重值最小的两个结点在数组中的位置void Select(HuffmanTree HT, int end, i...

2020-05-04 10:27:38 194

原创 IO复用-epoll的简易解析

参考这篇前提linux中将任何事务的输入输出都认为是文件读写,因此epoll事件也不例外,epoll有自己对应的文件系统,称为eventpollfs,epoll事件的创建,修改,删除都是在这个文件系统中进行的EPOLL结构epoll监听事件大体流程创建一个epoll结构体,结构体中保存监听的fd进入阻塞,当监听到某个或者某些fd有数据之后,就将对应的fd放到fd列表的头...

2020-05-02 00:24:07 142

原创 lambda表达式

lambda表达是一个没有名字的函数,有点类似于inline声明的函数[外部变量访问方式说明符] (参数表) -> 返回值类型{ 语句块}其中,“外部变量访问方式说明符”可以是=或&表示{}中用到的、定义在{}外面的变量在{}中是否允许被改变。=表示不允许,&表示允许。当然,在{}中也可以不使用定义在外面的变量。“-> 返回值类型”可以省略...

2020-05-02 00:06:09 97

空空如也

空空如也

TA创建的收藏夹 TA关注的收藏夹

TA关注的人

提示
确定要删除当前文章?
取消 删除