- 博客(21)
- 收藏
- 关注
原创 MySQL必会50题(1)
接下来要做分组操作,根据s_id和s_name分组,为啥不就根据s_id来分组?思路:先从teacher表中根据老师名字查询出张三的教师id,再根据这个教师id从课程表中查询出他教的课的id,再从分数表中根据这个课的id查询出选了这门课的学生,再从学生表中查询出学号不在选了这门课的学号中的学生。思路:先分别查询课程编号为01和课程编号为02的信息,将这两张表做内连接,得到了一张由s_id、01课程的成绩、02课程的成绩组合而成的一张表,然后再从这张表中查询到01的课程成绩比02高的学号。
2023-10-03 16:26:24
85
原创 volatile能否保证线程安全
原子性:一个线程内多行代码以一个整体运行,期间不能有其他线程的代码插队。可见性:一个线程对共享变量进行修改,另一个线程能看到最新的结果。有序性:一个线程内代码按编写顺序执行。
2023-02-25 12:48:57
136
原创 HashMap面试题
1.8数组+(链表|红黑树)链表过长,则会严重影响 HashMap 的性能,红黑树搜索时间复杂度是 O(logn),而链表是糟糕的 O(n)。hash表的查找,更新的时间复杂度是O(1),而红黑树的查找,更新的时间复杂度是O(log2n),TreeNode占用空间也比普通Node的大,因此如非必要,尽量还是使用链表。hsah值如果足够随机,则在hash表内按泊松分布,在负载因子0.75的情况下,长度超过8的链表出现的概率是0.00000006(亿分之6),选择8就是为了让树化几率足够小。
2023-02-21 13:25:15
121
原创 ArrayList和LinkedList的比较
尾部插入、删除性能可以,其他部分插入、删除都会移动数据,因此性能会很低。随机访问块(根据下标进行访问)可以利用cpu缓存,局部性原理。随机访问慢(要沿着链表遍历)基于双向链表,无需连续内存。基于数组,需要连续内存。
2023-02-15 22:56:11
125
原创 ArrayList扩容机制
addAll(Collection c)没有元素时,扩容为Math.max(10,实际元素个数),有元素时为Math.max(原容量1.5倍,实际元素个数)add(Object o)首次扩容为10,再次扩容为上次容量的1.5倍,底层扩容机制为原数向右移一位再加上原数的值。extends E>c)会使用c的大小作为数组容量。ArrayList(int initialCapacity)会使用指定容量的数组。ArrayList()会使用长度为零的数组。
2023-02-14 00:19:54
59
原创 快速排序之单边和双边循环
每一轮排序选择一个基准点(pivot)进行分区让小于基准点的元素进入一个分区,大于基准点的元素进入另一个分区当分区完成时,基准点元素的位置就是其最终位置在子分区内重复以上过程,直至子分区的元素个数小于等于1,这体现的是分而治之的思想(divide-and-conquer)
2023-02-14 00:03:19
334
原创 插入排序的优化
将数组分为两个区域,排序区域和未排序区域,每一轮从未排序区域取出第一个元素,插入到排序区域(需要保证顺序)待插入元素进行比较时,遇到比自己小的元素,就代表找到了插入位置,无需进行后续比较。插入排序属于稳定排序算法,而选择排序属于不稳定排序。插入时可以直接移动元素,而不是交换元素。二者的平均时间复杂度都是O(n^2)有序集合插入的时间复杂度为O(n)重复以上步骤,直到整个数组有序。大部分情况下,插入都略优于选择。
2023-02-12 16:01:59
73
原创 选择排序及优化
冒泡排序属于稳定排序算法,而选择属于不稳定排序(稳定性:指会不会对相同值的数据位置发生改变),冒泡排序,遇到相同值的时候不会交换数据位置,选择排序可能会交换数据位置。将数组分为两个子集,排序的和未排序的,每一轮从未排序的子集中选出最小元素,放入排序子集。为减少交换次数,每一轮可先找到最小索引,为每轮的最后交换元素。选择排序一般要快于冒泡,因为其交换次数少。二者的平均时间复杂度都是O(n^2)但如果集合有序度较高,冒泡优于选择。重复以上步骤,直到整个数组有序。
2023-02-12 15:40:49
57
原创 冒泡排序实现以及优化
可以发现,4、5、6的数组顺序已经排好,但却多比较了几轮,因此可以利用一个boolean变量来标记是否发生交换,如果发生交换则继续进行冒泡,如果没有发生交换,说明数组已经排好,退出循环。优化方式:每轮冒泡时,最后一次交换的索引可以作为下一轮冒泡的比较次数,如果这个值为0,表示整个数组有序,直接退出外循环即可。如果数组后面的数已经排好序,不必要继续进行冒泡,只需记录最后发生交换的元素索引下标即可,如果元素的下标为0,则排序结束。因为每次冒泡排序后,最后一个元素的位置被排好了,因此比较次数应根据排序轮数递减。
2023-02-12 14:30:56
155
原创 二分查找-解决整数溢出
left/2 +right/2 => left-left/2+right/2 =>left +(right-left)/2,这样可以保证right除以2不会发生溢出。整数溢出例子:左边界初始为0,右边界初始为int型最大值,第一次取mid时可以正常输出,第二次取mid时就会发生溢出,如下图。A[M]>T,中间值右侧的其他元素都大于T,无需比较,到中间索引的左侧去找,M-1设置为右边界。A[M]
2023-02-11 13:46:16
343
原创 LeetCode 101.对称二叉树(Java)
递归左节点的左节点和右节点的右节点,看他们是否对称,返回如果为true,则外侧相等。递归左节点的右节点和右节点的左节点,看他们是否对称,返回如果为true,则内侧相等。本题判断一棵二叉树是否对称,利用后序遍历,左--右--中的顺序。如果外侧和内侧同时为true,则这棵二叉树对称。巩固了递归的思想,这道题的重点是后序遍历。如果左节点为空,右节点不为空,不对称。如果左节点不为空,右节点为空,不对称。如果左节点为空,右节点也为空,对称。如果左节点的值不等于右节点,不对称。
2023-01-11 00:45:27
81
原创 LeetCode 226.反转二叉树(Java)
先定义一个整数len用来表示队列的长度que.size(),当len-->0时,从队列中取出一个节点,交换这个节点的左右子树,然后判断左右子节点是否为空,然后再把节点的左右子节点加入到que中。当节点不为空时,将其加入到队列中,当队列不为空的时候,开始遍历。可用多种方法来做,这里给出递归和层序遍历的做法。层序遍历法要借助queue这个数据结构。最后不断遍历每一层,最终返回root。重新复习了一遍递归法和层序遍历法。如果根节点为空,则直接返回。递归左子节点,递归右子节点。
2023-01-10 22:40:10
349
原创 LeetCode 111.二叉树的最小深度(Java)
先定义一个整数len用来表示队列的长度que.size(),当len-->0时,mindepth++,然后从队列中取出一个节点,如果左右节点同时为空,则找到了最小深度并返回,否则判断左右子节点是否为空,再把节点的左右子节点加入到que中。判断一个二叉树的最小深度是通过层序遍历找到第一个左右节点都为空的节点。层序遍历法除了要返回的list之外还要借助queue这个数据结构。当节点不为空时,将其加入到队列中,当队列不为空的时候,开始遍历。如果根节点为空,则直接返回。本题可采用层序遍历法。
2023-01-10 00:13:36
53
原创 LeetCode 104.二叉树的最大深度(Java)
先定义一个整数len用来表示队列的长度que.size(),当len-->0时,从队列中取出一个节点,判断左右子节点是否为空,然后再把节点的左右子节点加入到que中。这题虽然是模板题,但是要注意depth的位置,是遍历完一层后再++层序遍历法除了要返回的list之外还要借助queue这个数据结构。当节点不为空时,将其加入到队列中,当队列不为空的时候,开始遍历。遍历完一层后,也就是跳出一层while循环后,depth++如果根节点为空,则直接返回。本题可采用层序遍历法。
2023-01-09 23:59:20
112
原创 Leetcode 116.填充每个节点的下一个右侧节点指针(Java)
先定义一个整数len用来表示队列的长度que.size(),当len-->0时,从队列中取出一个节点,如果len不等于0(poll出来的节点不是本层最后一个),使节点指向本层下一个节点(下一个节点已在队列中,所以peek一下就ok),然后再把节点的左右子节点加入到que中。层序遍历法除了要返回的list之外还要借助queue这个数据结构。当节点不为空时,将其加入到队列中,当队列不为空的时候,开始遍历。循环遍历每一层给,返回root。如果根节点为空,则直接返回。本题可采用层序遍历法。
2023-01-09 23:44:34
73
原创 Leetcode 515.在每个树行中找最大值(java)
先定义一个整数size用来表示队列的长度que.size(),然后定义一个int类型的max,将其赋值为int的最小值Integer.MIN_VALUE,注意这里不能将其初始化为0,因为二叉树的值有可能为负数,-231
2023-01-09 23:17:49
69
原创 LeetCode 429.N叉树的层序遍历(java)
当len-->0时,从队列中poll出一个节点,将他的值add进list中,再看它的孩子是否为空,如果不为空,则将孩子加入到新定义的列表中,遍历这个列表,将每一个孩子的值加入到队列当中,当len=0则表示这一层的节点已经遍历完了,队列中如果还有剩余的节点是下一层的了。因为输出结果是一个二维的数组,所以先定义一个list用来集合每一层的list,然后定义一个队列来遍历二叉树。当节点不为空时,将其加入到队列中,当队列不为空的时候,开始遍历。最后将每一层的list加入到result中,退出循环将其返回。
2023-01-07 17:05:25
110
原创 LeetCode 637.二叉树的层平均值
先定义一个整数size用来表示队列的长度que.size(),然后定义一个double类型的sum。循环遍历这一层,sum+=每一个节点的值,并将每一个节点的左右孩子加入到队列中。层序遍历法除了要返回的list之外还要借助queue这个数据结构。当节点不为空时,将其加入到队列中,当队列不为空的时候,开始遍历。将每一层的sum/size的值加入到result。如果根节点为空,则直接返回。本题可采用层序遍历法。
2023-01-07 16:36:32
85
原创 LeetCode 199.二叉树的右视图
当size>0时,从队列中poll出一个节点,如果此时size==1,说明遍历到本层的最后一个节点,将他的值add进list中,否则,看它的左右孩子是否为空,如果不为空,则将其加入到队列中,当size==0则表示这一层的节点已经遍历完了,队列中如果还有剩余的节点是下一层的了,size--先定义一个整数size用来表示队列的长度que.size(),然后定义一个list来接收这一层的的节点的值。当节点不为空时,将其加入到队列中,当队列不为空的时候,开始遍历。如果根节点为空,则直接返回。本题可采用层序遍历法。
2023-01-07 16:11:05
42
原创 LeetCode 107.二叉树的层序遍历 ||(java)
反转链表遍历List时,得到每一层应该用get方法。和102.二叉树的层序遍历前面的步骤一样,最后反转一下链表。
2023-01-07 15:51:03
40
原创 Leetcode 102.二叉树的层序遍历(java)
当len-->0时,从队列中poll出一个节点,将他的值add进list中,再看它的左右孩子是否为空,如果不为空,则将其加入到队列中,当len=0则表示这一层的节点已经遍历完了,队列中如果还有剩余的节点是下一层的了。定义泛型为list的list:List result = new ArrayList();因为输出结果是一个二维的数组,所以先定义一个list用来集合每一层的list,然后定义一个队列来遍历二叉树。如果根节点为空,则直接返回。
2023-01-07 13:55:07
189
1
空空如也
空空如也
TA创建的收藏夹 TA关注的收藏夹
TA关注的人