Java 学习总结 Week2

本周一些学习方法反思:

​ 1.完美主义与囫囵吞枣

​ 2.思考是好事,焦虑是浪费时间。譬如刚跟我实验室导师谈话,下学期打算准备退出实验室,明年打算实习,老师也会耐心给我分析读研与工作的利与弊。当然工作这个选择身边的同学似乎选择地比较少,似乎不太主流,but whatever。做出一个选择,去分析其他选择的利弊成本可能性是好事,但倘若每时每刻都在犹豫不舍,那只能是耽误时间。这个社会充满不确定性,充满竞争,我相信学历只是能体现能力的标签之一,但最本质最关键的还是自身的能力。

​ 我们不可能在选择之前就知道最适合自己的选择是哪个,有些选择只有做了才能看出适不适合自己以及是否真的如大家所预设想的那样。与其纠结迷茫,不如果断地选择。也许长路漫漫,殊途同归。

​ 3.这周本来打算继续学Java SE的,学着感觉光看视频写写总结好像还是缺少了点实践,所以还是打算开始一边用Java刷刷Leetcode,一边再学Java基础。毕竟算法这块面试也是必须要过的,而且编程能力这块速成是比较困难的,需要大量时间大量练习积累,所以尽早开始准备没有坏处,所以接下学习Java的进度可能会逐渐减慢,重点会逐渐从语法基础转移到进阶的知识方面,当然这部分也是需要大量时间学习的。如:

  1. Java集合类源码

  2. 线程池

  3. Java代理

  4. IO模型

  5. JVM

  6. Java并发编程

  7. 框架使用等等

    ​ 对于项目的准备,我打算这两周先暂时放下,感觉需要学习的基础还有比较多,如项目准备需要先学数据库相关内容,还是简单提前了解一下比较好,而且这部分知识面试也是经常会问到的。在参考相关面经后,项目的重要性似乎在应届生实习比重会有所降低,重要的确实还是基础基础!无论是对基础知识的理解还是编程算法能力等,接下来也会有意识地培养这两个方面。

    ​ 毕竟算法题刷起来少了点熟练度,估计面试也会少了点底气。

™本周学习总结

1.String类

Java StringBuffer 和 StringBuilder 类

这部分内容比较多也比较杂,后续复习的时候再细致梳理。

2.容器和C++STL

​ 这部分内容刚开始是打算看的,想了想还是先了解常用的方法,先学会用容器写写算法题,后续深入学习时候再继续研究相关源码方面,不然现在接触首先很容易忘记细节,理解得不那么深入,二是是入门时间偏长,由于后续要学数据库,所以想把后面的计划提一提。而且想做的项目需要用到数据库方面知识,延后学习的话不知道开学后还有没有这么一大段空闲的时间(毕竟会有各种各样课程的作业要求等等),所以趁早学习项目基础然后入手,更有针对性的学习比较好。许多面经八股文也重点提到了集合源码部分的重要性,所以后续也会重点慢慢看。

​ 这部分知识还是在刷题前得首先看一看的,比如今天遇到的问题用Deque来解决比较高效,首先我们得知道Deque的特性,熟悉它,知道它适合怎么用,方法有哪些,刷题或做项目的时候才会想到用这个数据结构来优化。

这周只看了List部分,包括ArrayList的底层实现,如扩容机制等等,与C++Vector有类似之处,之后深入了解时再细致对比。

3.Comparable 和 Comparator 接口的区别

Java 解惑:Comparable 和 Comparator 的区别

JAVA中Arrays.sort()使用两种方式(Comparable和Comparator接口)对对象或者引用进行排序

4.接口

接口和抽象类区别和联系
实现接口和继承
Java可以多继承interface,而不可以多继承class

5.内部类

在这里插入图片描述

匿名内部类(重点)

​ 思考为什么需要匿名内部类

成员内部类

静态内部类 static+成员内部类

在这里插入图片描述

算法前预备:

Java Arrays 常用方法

Java中Arrays.sort()自定义数组的升序和降序排序

二分查找复习

细节tricky

普通二分查找:

搜索空间:[0,arr.length-1]

是否一定有解? 不一定,所以需要搜索最后一个元素。while 中用 left<right 退出循环时遗漏搜索了一个元素

其实只要清楚搜索的概念,while循环里面写小于是没有问题的,在返回结果再判断最后一个元素是否为target就可以了。

最基础的两种变种

1.寻找小于target的最大值 lower

搜索空间 :(极端情况帮助确定搜索空间)

​ target 小于数组最小值时应该返回-1,即left=-1

​ target 大于数组最大值时应该返回数组最大值的索引,即right=arr.length-1

搜索空间为 [-1,arr.length-1]

是否一定有解? 一定!搜索区间最后一个值即为解!因此while循环中可以用left<right,用<=则有可能出现死循环问题;

因为同普通二分搜索不同,当arr[mid]<target时,如果此时l==r,区间不会发生变化而且会继续循环,原因是我们下面搜索逻辑决定的,因为当arr[mid]<target时,此时的mid有可能就为答案,但是我们不能退出循环, 因为有可能mid右侧有更合适的答案,所以我们需要将mid纳入搜索范围继续搜索,而当搜索空间只剩mid时就不会再更新区间了,因为此时left=right,此时就是寻找到了答案,因此应该退出循环。

lower的问题 例如arr[]={1,1,3,3,5,5}

程序会进入死循环,原因是计算机整形除法时取了左边界使得搜索空间没有发生改变。

解决方案:mid=l+(r-l+1)/2(mid=(left+right+1)/2)

下面举例说明采用普通的mid计算会发生什么情况:

mid=(left+right)/2

arr[mid]=target时 (此时mid不可能为解,更新边界,在左侧继续搜索更小的值)

左边界变化情况: 不变

右边界变化情况: r=mid-1

arr[mid]<target时(此时mid 有可能为解,纳入搜索范围,继续搜索有没有比target更小且比mid更大的值,在右侧搜索)

左边界变化情况: l=mid

右边界变化情况: 不变

arr[mid]>target时(此时mid不可能为解,更新边界,在左侧区域进行搜索)

左边界变化情况: 不变

右边界变化情况: r=mid-1

我们可以通过极端情况进行tricky的细节debug,如l和r相邻时,mid会取左侧边界,即left。当l、r相邻且arr[l]<target时,

此时左侧边界是不会进行更新的,也就陷入了死循环。我们可以通过让mid’取右侧边界right来规避这种情况,因为如果每次取右边界,

l=mid也会更新到右侧边界,相当于无论哪种情况边界都会进行更新。

2.寻找大于target的最小值 upper

搜索空间:target 小于最小值时应该返回0,left=0

​ target 大于最大值时需要返回数组最大值右边的索引 即 right=arr.length

搜索空间为[0,arr.length]

是否一定有解? 一定!搜索区间最后一个值即为解!因此while循环中可以用left<right,用<=则有可能出现死循环问题;

不存在lower的left和right相邻死循环问题,此时左边界一定会发生改变,当left和right相邻时,

mid=(left+right)/2 取左边界,所以区间必然会改变

下面举例说明采用普通的mid计算会发生什么情况:

mid=(left+right)/2

arr[mid]=target时 (此时mid不可能为解,更新边界,在右侧继续搜索更大的值)

*左边界变化情况: l=mid+1

*右边界变化情况: 不变

arr[mid]<target时(此时mid 不可能为解,在右侧搜索更大的值)

*左边界变化情况: l=mid+1

右边界变化情况: 不变

arr[mid]>target时(此时mid有可能,纳入下一次搜索范围,在左侧区域进行搜索,寻找有没有比mid更小但比target更大的目标值,没有的话mid即为答案)

左边界变化情况: 不变

*右边界变化情况: r=mid

在这里插入图片描述

我们可以看到,mid取left 和 right 中间(向下取整)偏左的结果,即当left和right相邻时取左边界,此时r=mid会更新到左侧边界,即无论哪种情况边界都会更新,不用担心进入死循环的问题。

3.寻找右侧边界的二分搜索以及寻找大于target值的最小值位置(upper_ceil)

等于target时,返回target的最大索引,不存在target时,返回大于target的最小值

既然最大索引,那么我们可以转换问题,无论target存不存在,我们都找大于target的最小值

搜索空间:[0,arr.length]

是否一定有解?一定!

分析

arr[mid]=target时 (此时mid不可能为解,在其右侧区域继续进行搜索

左边界变化情况: l=mid+1

右边界变化情况: 不变

arr[mid]<target时(此时mid 不可能为解)

左边界变化情况: l=mid+1

右边界变化情况: 不变

arr[mid]>target时(此时mid有可能为解,需要继续将此解纳入下一次搜索范围,并在其左侧区域进行搜索)

左边界变化情况: 不变

右边界变化情况: r=mid

我们要注意此时的返回结果为left==right ,这里比较tricky的部分在于我们要理解结果返回的是什么,返回的是upper(比target大的最小元素),因此这个坐标值-1(arr[left-1]只有两种情况,要么等于target(此时应该返回left-1),要么不等于target(此时应该返回left))

4.寻找左侧边界的二分搜索以及寻找大于等于target的最小索引(lower_ceil)

等于target时,返回target的最小索引,不存在target时,返回大于target的最小值(upper)

思考一下,问题其实是求大于等于target的最小索引

upper问题求的是大于target时的最小索引,

upper_ceil求的是两种情况 大于target时的最小索引(upper)+ 等于target时的最大索引

upper_ceil两种情况其实是相邻的,所以能转换为upper问题

Lower_ceil问题

搜索空间 : [0,arr.length]

同上述分析

在这里插入图片描述

这里我们必须清楚返回的结果((left==right)表示什么)

比较upper,我们发现仅在 arr[mid]==target时做出了改变,原因就在于搜索区间的变化,lower_ceil当存在target值时要继续往target及target左侧继续搜索。

在这里插入图片描述

5.lower_floor

存在元素target 返回最小索引

不存在元素,返回lower (小于target的最大索引)

两种情况结果相邻,转换问题为寻找小于target的最大值 lower

只需要在返回结果判断 left+1是否 ==target

6.upper_floor

存在元素target 返回最大索引

不存在元素,返回lower (小于target的最大索引)

其实可以理解为返回小于等于target的最大索引)

搜索空间:[0,arr.length]

分析:

arr[mid]=target时 (此时mid有可能为解,需要继续将此解纳入下一次搜索范围,并在其左侧区域进行搜索)

左边界变化情况: 不变

右边界变化情况: r=mid

arr[mid]<target时(此时mid 不可能为解)

左边界变化情况: l=mid+1

右边界变化情况: 不变

arr[mid]>target时(此时mid有可能为解,需要继续将此解纳入下一次搜索范围,并在其左侧区域进行搜索)

左边界变化情况: 不变

右边界变化情况: r=mid

*注意mid的计算向下取整,可以理解为mid取左边界,*所以无论是r=mid,还是 l=mid+1边界都会进行改变,没有死循环问题;

Tricky Exercise

Leetcode
**** 34. 在排序数组中查找元素的第一个和最后一个位置
**** 33. 搜索旋转排序数组
****162. 寻找峰值
****287. 寻找重复数
****154. 寻找旋转排序数组中的最小值 II(比较特别的target值比较)
****81. 搜索旋转排序数组 II(这题与上题有所不同,尽管都是有重复元素的二分)(很tricky,但做完感觉会增加对二分区间移动的判断)
****540. 有序数组中的单一元素(根据位置的奇偶更新二分搜索区间)

滑动窗口

这部分看的Labuladong算法小抄,觉得写得挺不错的,基本上背过框架稍微改变下模板内容就能解决这相关方面的问题

76. 最小覆盖子串

567. 字符串的排列

tricky部分Integer的==与equals

回溯法

79. 单词搜索(注意如何搜索,如何回撤,回撤什么)
934. 最短的桥(非常值得一做的综合dfs和bfs)
126. 单词接龙 II(同样非常精彩的一道题,做完这题(虽然是看了题解),最后自己重新梳理一遍代码,感觉对Java几乎所有常用的集合以及BFS、DFS有了更深的理解)
47. 全排列 II(写过两次这道题第三次写还是写不出来…面壁思过)
39. 组合总和(搜索范围,如何解决重复范围,逐渐头秃)
40. 组合总和 II(剪枝大幅降低复杂度,思考递归树,同层级以及不同层级的重复问题如何优化)

这里有个很tricky的细节

什么时候使用 used 数组,什么时候使用 begin 变量
有些朋友可能会疑惑什么时候使用 used 数组,什么时候使用 begin 变量。这里为大家简单总结一下:

排列问题,讲究顺序(即 [2, 2, 3] 与 [2, 3, 2] 视为不同列表时),需要记录哪些数字已经使用过,此时用 used 数组;
组合问题,不讲究顺序(即 [2, 2, 3] 与 [2, 3, 2] 视为相同列表时),需要按照某种顺序搜索,此时使用 begin 变量。
注意:具体问题应该具体分析, 理解算法的设计思想 是至关重要的,请不要死记硬背。

作者:liweiwei1419
链接:https://leetcode-cn.com/problems/combination-sum/solution/hui-su-suan-fa-jian-zhi-python-dai-ma-java-dai-m-2/

动态规划

SomethingElse

在这里插入图片描述

下周学习安排

1.老韩Java基础部分,Java数据库内容

2.《Leetcode101》刷起(动态规划.etc)

3.《MySQL是怎样运行的》与《SQL必知必会》结合阅读

4.JDK8 Stream 了解

最容易的是开始,最难的是坚持。

很多时候不是因为看到意义才坚持,而是坚持才能看到意义。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值