1.约瑟夫环问题
![](https://img.haomeiwen.com/i2916604/551b5e605cb49ece.png)
![](https://img.haomeiwen.com/i2916604/0eaf1d546f6f0854.png)
示例代码:
![](https://img.haomeiwen.com/i2916604/361ad16171f89115.png)
![](https://img.haomeiwen.com/i2916604/2cb5b3dca80e0e2d.png)
![](https://img.haomeiwen.com/i2916604/84349fa2fe676779.png)
2. 链表节点
![](https://img.haomeiwen.com/i2916604/f6bc63f2517a2df0.png)
![](https://img.haomeiwen.com/i2916604/25355e2c359e5a26.png)
![](https://img.haomeiwen.com/i2916604/0d8a58a1b4e7e339.png)
<strong>
解法一:空间O(1) 空间O(M*N)
![](https://img.haomeiwen.com/i2916604/15677d25e8d0cbf2.png)
实现代码:
![](https://img.haomeiwen.com/i2916604/67b2a597c8a31690.png)
解法二:
![](https://img.haomeiwen.com/i2916604/a24e0dbdc571640f.png)
![](https://img.haomeiwen.com/i2916604/e358989d1fbcc547.png)
解法三:
![](https://img.haomeiwen.com/i2916604/740741f7adecc0ab.png)
![](https://img.haomeiwen.com/i2916604/dda46c954bd4671c.png)
实现代码:
![](https://img.haomeiwen.com/i2916604/16474e6047089ecc.png)
![](https://img.haomeiwen.com/i2916604/46e772522320fe32.png)
![](https://img.haomeiwen.com/i2916604/d1fdc1c3289e8600.png)
3. 判断链表有环
![](https://img.haomeiwen.com/i2916604/7dd7e58e24b23702.png)
![](https://img.haomeiwen.com/i2916604/b3f69f41715f61b0.png)
![](https://img.haomeiwen.com/i2916604/59e98a6e2194179d.png)
实现代码:
![](https://img.haomeiwen.com/i2916604/90b886dd39e37910.png)
4 链表环的起始节点
![](https://img.haomeiwen.com/i2916604/e18cac274ced6c66.png)
<strong>思路:解决这道问题的关键就是知道:
![]()
举例子:如下图设头结点到链表环起始节点的距离为a,链表环节点数为b,
快指针fast每次走两步,慢指针每次走一步。
![]()
可以看到此时a=2,b=6
![](https://img.haomeiwen.com/i2916604/758a108f20d93889.png)
而且可以知道,每次慢指针走一步,和快指针的差距就加1,因为慢指针和快指针一开始都在头结点,所以:
- 当慢指针走了a部到达链表环节点时,此时和快指针的距离也为a。
- 此时快指针和慢指针相聚(b-a),所以快指针还需要走(b-a)次才能追上慢指针。
- 这也意味着,慢指针要从链表环节点开始走(b-a)步就和快指针相遇。
-
此时从链表环开始节点已经走了(b-a)步,所以再走b-(b-a)=a步就可以回到链表环节点。
所以:
解题思路:根据以上结论,先测定是否有环,找到快慢指针的相遇节点,然后定义另一个指针为头节点,从头结点和相遇节点开始向后遍历,不断判断是否相同,得到相同的节点就是链表环开始结点!
-
寻找重复元素
暴力求解法:
哈希表法
![](https://img.haomeiwen.com/i2916604/ceeb0172ae7eba53.png)
![](https://img.haomeiwen.com/i2916604/890dfc594d3d57b5.png)
数组环法
对于一个给定数组我们可以可以看成一个个节点,数组下标表示当前节点的值,而其对应的数组值可以看做节点的next,把该值当做数组下标可以找到下一个“节点值”
![](https://img.haomeiwen.com/i2916604/c2ea049d19c8de67.png)
对于数组下标【0到n+1】的数组,如若往里边填入【0到n】个数,而且不重复。从大的数组下标开始可以得到一条不带环的链表。
![](https://img.haomeiwen.com/i2916604/5d5f3e81b38da104.png)
可以看到此时有唯一一个没有对应元素值的数组下标5,里边若对应任何重复元素都将形成链表环。(加入现在填个1)
这个原理也很简单普通无环的链表,每个节点的next值都应该是唯一。但假如给尾节点(next指向为null的节点)指向前边的链表节点(相当于给5添加重复值1),那么链表必将为环。
![]()
此时可以知道,链表环起始节点就是,数组里边的重复元素。
这里有三个重点需要注意:
一、 够成这样子数组环的关键是加入index的下标最大值为n+1的话,那么对应的元素值最大值应该为n。
假如上图的下标7要是对应元素也是7的话,很明显就变成一个自循环,无法串联其他元素。
![]()
二、 链表头结点要从最大数组下标开始,也就是从右往左。因为如果从左往右的话可能无法遍历到所有元素。(假如从0开始)
![](https://img.haomeiwen.com/i2916604/b10df5e025507b8c.png)
<strong>这里分两方面来分析:
- 为什么从最大数组下标开始呢?
首先我们知道一个链表的头结点时没有前驱节点的,前面我们也知道了对数组下标最大为n+1的数组来说,元素值最大应该为n,前面我们也说了,元素值可以理解为next节点。也就数说没有节点的next值能达到n+1,数组下标为n+1的节点没有所谓的前驱节点,所以必然是头结点。
而除了下标为n+1的节点都有前驱节点所以从它们开始遍历的话链表将不完整。 - 即使有若干个字循环的节点,也不影响找到重复元素(会跳过那些非重复自循环的节点)。
![](https://img.haomeiwen.com/i2916604/c01716c3adb458eb.png)
理解了以上内容就把这题当做,寻找链表环节点就行啦,注意:题目给的元素值为1n,下标对应为0n,所以在遍历的时候记得减一。
实现代码
![](https://img.haomeiwen.com/i2916604/7298f2125c994f08.png)
(看见这种提交结果最开心了~~)
![](https://img.haomeiwen.com/i2916604/06df011e6a2171d9.png)
网友评论