示例 1:
输入:head = [3,2,0,-4], pos = 1
输出:true
解释:链表中有一个环,其尾部连接到第二个节点。
示例 2:
输入:head = [1], pos = -1
输出:false
解释:链表中没有环。
进阶:
你能用 O(1)(即,常量)内存解决此问题吗?
思路:首先我们要明白,链表不可能出现这种情况:
因为一个结点只有一个指针,所以链表只可能向实例一那样,在末尾出现一个环。
慢指针一次一步,快指针一次两步。能相遇就是有环,反之没有环。就像操场跑步,跑的快的总有一天可以追慢的一圈,相遇。
/**
-
Definition for singly-linked list.
-
class ListNode {
-
int val;
-
ListNode next;
-
ListNode(int x) {
-
val = x;
-
next = null;
-
}
-
}
*/
public class Solution {
public boolean hasCycle(ListNode head) {
if (head == null || head.next == null) {
return false;
}
ListNode slow = head;
ListNode fast = head.next;
while (slow != fast) {
if (fast == null || fast.next == null) {
return false;
}
slow = slow.next;
fast = fast.next.next;
}
return true;
}
}
那么,这对于懂算法的人来说可能是烂大街的问题,有些人可能不屑于看了,那么,第二个问题来了:如果让那个快指针一次走三步,还能不能做正确的答案呢?一次四步呢?五步呢?
如果看的人多,我会在下一期公布答案哈哈,大家不要以为应试被题就可以过关。
2)介绍一下堆这种数据结构
大根堆要求
①根节点的关键字既大于或等于左子树的关键字值,又大于或等于右子树的关键字值。
②为完全二叉树。
注意这是递归定义的。
对于大根小根堆,递归定义,实现,空间复杂度,各种操作的时间复杂度,真实写二叉树的情况和数组模拟的情况都要会。
有人要问了,会这些算法有啥用?其实Java的优先队列就是堆结构。八大排序之一的堆排序也是数组上堆结构,面试官让我手动实现一个,以下是实现。
/*
================================================
功能:堆排序
输入:数组名称(也就是数组首地址)、数组中元素个数
注:画画
================================================
*/
/*
功能:建堆
输入:数组名称(也就是数组首地址)、参与建堆元素的个数、从第几个元素开始
*/
void sift(int *x, int n, int s)
{
int t, k, j;
t = *(x+s); /暂存开始元素/
k = s; /开始元素下标/
j = 2*k + 1; /左子树元素下标/
while (j<n)
{
if (j<n-1 && *(x+j) < *(x+j+1))/判断是否存在右孩子,并且右孩子比左孩子大,成立,就把j换为右孩子/
{
j++;
}
if (t<*(x+j)) /调整/
{
*(x+k) = *(x+j);
k = j; /调整后,开始元素也随之调整/
j = 2*k + 1;
}
else /没有需要调整了,已经是个堆了,退出循环。/
{
break;
}
}
*(x+k) = t; /开始元素放到它正确位置/
}
/*
功能:堆排序
输入:数组名称(也就是数组首地址)、数组中元素个数
注:
-
*
-
-
建堆时,从从后往前第一个非叶子节点开始调整,也就是“-”符号的位置
*/
void heap_sort(int *x, int n)
{
int i, k, t;
//int *p;
for (i=n/2-1; i>=0; i–)
{
sift(x,n,i); /初始建堆/
}
for (k=n-1; k>=1; k–)
{
t = *(x+0); /堆顶放到最后/
*(x+0) = *(x+k);
*(x+k) = t;
sift(x,k,0); /剩下的数再建堆/
}
}
3)排序知道哪些?来介绍介绍?
答:全知道,全会写,然后只说了冒泡的所有思路和优化、和快排BFPRT就被叫停了。我就把所有排序介绍和实现分享给大家。
一面结束,面试小哥表示对我很满意,说马上让另外一个人二面。
二面:
二面小哥说,一面说你算法贼强,咱们这次就不聊算法了,说说项目。
4)看我项目里用了redis,就问redis都有哪些数据结构。
我说有string、list、hash、set、zset。
问:你说的这些Java以及其他语言基本也都有,你说了解redis,那这些数据结构到底是不是快?咋实现的呢?
我举例子说了一下:
- 1) 字符串
redis并未使用传统的c语言字符串表示,它自己构建了一种简单的动态字符串抽象类型。
当需要一个可以被修改的字符串时,redis就会使用自己实现的SDS(simple dynamic string)。比如在redis数据库里,包含字符串的键值对底层都是SDS实现的,不止如此,SDS还被用作缓冲区(buffer):比如AOF模块中的AOF缓冲区以及客户端状态中的输入缓冲区。
下面来具体看一下sds的实现:
-
struct sdshdr
-
{
-
int len;//buf已使用字节数量(保存的字符串长度)
-
int free;//未使用的字节数量
-
char buf[];//用来保存字符串的字节数组
-
};
sds遵循c中字符串以’\0’结尾的惯例,这一字节的空间不算在len之内。
这样的好处是,我们可以直接重用c中的一部分函数。比如printf;
sds相对c的改进
获取长度:c字符串并不记录自身长度,所以获取长度只能遍历一遍字符串,redis直接读取len即可。
缓冲区安全:c字符串容易造成缓冲区溢出,比如:程序员没有分配足够的空间就执行拼接操作。而redis会先检查sds的空间是否满足所需要求,如果不满足会自动扩充。
内存分配:由于c不记录字符串长度,对于包含了n个字符的字符串,底层总是一个长度n+1的数组,每一次长度变化,总是要对这个数组进行一次内存重新分配的操作。因为内存分配涉及复杂算法并且可能需要执行系统调用,所以它通常是比较耗时的操作。
自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。
深知大多数Java工程师,想要提升技能,往往是自己摸索成长或者是报班学习,但对于培训机构动则几千的学费,着实压力不小。自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!
因此收集整理了一份《2024年Java开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。
既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上Java开发知识点,真正体系化!
由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且会持续更新!
如果你觉得这些内容对你有帮助,可以扫码获取!!(备注Java获取)
如何快速更新自己的技术积累?
- 在现有的项目里,深挖技术,比如用到netty可以把相关底层代码和要点都看起来。
- 如果不知道目前的努力方向,就看自己的领导或公司里技术强的人在学什么。
- 知道努力方向后不知道该怎么学,就到处去找相关资料然后练习。
- 学习以后不知道有没有学成,则可以通过面试去检验。
我个人觉得面试也像是一场全新的征程,失败和胜利都是平常之事。所以,劝各位不要因为面试失败而灰心、丧失斗志。也不要因为面试通过而沾沾自喜,等待你的将是更美好的未来,继续加油!
以上面试专题的答小编案整理成面试文档了,文档里有答案详解,以及其他一些大厂面试题目
《互联网大厂面试真题解析、进阶开发核心学习笔记、全套讲解视频、实战项目源码讲义》点击传送门即可获取!
学什么。
- 知道努力方向后不知道该怎么学,就到处去找相关资料然后练习。
- 学习以后不知道有没有学成,则可以通过面试去检验。
我个人觉得面试也像是一场全新的征程,失败和胜利都是平常之事。所以,劝各位不要因为面试失败而灰心、丧失斗志。也不要因为面试通过而沾沾自喜,等待你的将是更美好的未来,继续加油!
以上面试专题的答小编案整理成面试文档了,文档里有答案详解,以及其他一些大厂面试题目
[外链图片转存中…(img-wxQV4dl3-1712698340086)]
[外链图片转存中…(img-YJyKo5yW-1712698340086)]
《互联网大厂面试真题解析、进阶开发核心学习笔记、全套讲解视频、实战项目源码讲义》点击传送门即可获取!