diff --git a/animation-simulation/链表篇/234. 回文链表.md b/animation-simulation/链表篇/234. 回文链表.md index a9d8cbb..cee4772 100644 --- a/animation-simulation/链表篇/234. 回文链表.md +++ b/animation-simulation/链表篇/234. 回文链表.md @@ -1,5 +1,3 @@ - - > 如果阅读时,发现错误,或者动画不可以显示的问题可以添加我微信好友 **[tan45du_one](https://raw.githubusercontent.com/tan45du/tan45du.github.io/master/个人微信.15egrcgqd94w.jpg)** ,备注 github + 题目 + 问题 向我反馈 > > 感谢支持,该仓库会一直维护,希望对各位有一丢丢帮助。 @@ -63,7 +61,6 @@ class Solution { return true; } } - ``` C++ Code: @@ -72,18 +69,23 @@ C++ Code: class Solution { public: bool isPalindrome(ListNode* head) { + //这里需要用动态数组,因为我们不知道链表的长度 vector arr; ListNode* copynode = head; + //将链表的值复制到数组中 while (copynode) { arr.push_back(copynode->val); copynode = copynode->next; } + //双指针遍历数组 int back = 0; int pro = arr.size() - 1; while (back < pro) { + //判断两个指针的值是否相等 if (arr[back] != arr[pro]) { return false; } + //移动指针 back++; pro--; } @@ -121,7 +123,7 @@ var isPalindrome = function(head) { Python Code: -```py +```python class Solution: def isPalindrome(self, head: ListNode) -> bool: arr = [] @@ -145,7 +147,7 @@ class Solution: 这个方法可以直接通过,但是这个方法需要辅助数组,那我们还有其他更好的方法吗? -双指针翻转链表法 +**双指针翻转链表法** 在上个题目中我们知道了如何找到链表的中间节点,那我们可以在找到中间节点之后,对后半部分进行翻转,翻转之后,重新遍历前半部分和后半部分进行判断是否为回文。 @@ -165,17 +167,17 @@ class Solution { } //找到中间节点,也就是翻转的头节点,这个在昨天的题目中讲到 //但是今天和昨天有一些不一样的地方就是,如果有两个中间节点返回第一个,昨天的题目是第二个 - ListNode midenode = searchmidnode(head); + ListNode midnode = searchmidnode(head); //原地翻转链表,需要两个辅助指针。这个也是面试题目,大家可以做一下 //这里我们用的是midnode.next需要注意,因为我们找到的是中点,但是我们翻转的是后半部分 - ListNode backhalf = reverse(midenode.next); + ListNode backhalf = reverse(midnode.next); //遍历两部分链表,判断值是否相等 ListNode p1 = head; ListNode p2 = backhalf; while (p2 != null) { if (p1.val != p2.val) { //若要还原,记得这里也要reverse - midenode.next = reverse(backhalf); + midnode.next = reverse(backhalf); return false; } p1 = p1.next; @@ -183,7 +185,7 @@ class Solution { } //还原链表并返回结果,这一步是需要注意的,我们不可以破坏初始结构,我们只是判断是否为回文, //当然如果没有这一步也是可以AC,但是面试的时候题目要求可能会有这一条。 - midenode.next = reverse(backhalf); + midnode.next = reverse(backhalf); return true; } //找到中点 @@ -222,17 +224,17 @@ public: } //找到中间节点,也就是翻转的头节点,这个在昨天的题目中讲到 //但是今天和昨天有一些不一样的地方就是,如果有两个中间节点返回第一个,昨天的题目是第二个 - ListNode * midenode = searchmidnode(head); + ListNode * midnode = searchmidnode(head); //原地翻转链表,需要两个辅助指针。这个也是面试题目,大家可以做一下 //这里我们用的是midnode->next需要注意,因为我们找到的是中点,但是我们翻转的是后半部分 - ListNode * backhalf = reverse(midenode->next); + ListNode * backhalf = reverse(midnode->next); //遍历两部分链表,判断值是否相等 ListNode * p1 = head; ListNode * p2 = backhalf; while (p2 != nullptr) { if (p1->val != p2->val) { //若要还原,记得这里也要reverse - midenode.next = reverse(backhalf); + midnode->next = reverse(backhalf); return false; } p1 = p1->next; @@ -240,7 +242,7 @@ public: } //还原链表并返回结果,这一步是需要注意的,我们不可以破坏初始结构,我们只是判断是否为回文, //当然如果没有这一步也是可以AC,但是面试的时候题目要求可能会有这一条。 - midenode->next = reverse(backhalf); + midnode->next = reverse(backhalf); return true; } //找到中间的部分 @@ -277,17 +279,17 @@ var isPalindrome = function(head) { } //找到中间节点,也就是翻转的头节点,这个在昨天的题目中讲到 //但是今天和昨天有一些不一样的地方就是,如果有两个中间节点返回第一个,昨天的题目是第二个 - let midenode = searchmidnode(head); + let midnode = searchmidnode(head); //原地翻转链表,需要两个辅助指针。这个也是面试题目,大家可以做一下 //这里我们用的是midnode.next需要注意,因为我们找到的是中点,但是我们翻转的是后半部分 - let backhalf = reverse(midenode.next); + let backhalf = reverse(midnode.next); //遍历两部分链表,判断值是否相等 let p1 = head; let p2 = backhalf; while (p2 != null) { if (p1.val != p2.val) { //若要还原,记得这里也要reverse - midenode.next = reverse(backhalf); + midnode.next = reverse(backhalf); return false; } p1 = p1.next; @@ -295,7 +297,7 @@ var isPalindrome = function(head) { } //还原链表并返回结果,这一步是需要注意的,我们不可以破坏初始结构,我们只是判断是否为回文, //当然如果没有这一步也是可以AC,但是面试的时候题目要求可能会有这一条。 - midenode.next = reverse(backhalf); + midnode.next = reverse(backhalf); return true; }; @@ -326,7 +328,7 @@ var reverse = function(slow) { Python Code: -```py +```python class Solution: def isPalindrome(self, head: ListNode) -> bool: if head is None or head.next is None: @@ -344,12 +346,11 @@ class Solution: if p1.val != p2.val: # 若要还原,记得这里也要reverse midnode.next = self.reverse(backhalf) - print(head) return False p1 = p1.next p2 = p2.next # 还原链表并返回结果,这一步是需要注意的,我们不可以破坏初始结构,我们只是判断是否为回文, - 当然如果没有这一步也是可以AC,但是面试的时候题目要求可能会有这一条。 + # 当然如果没有这一步也是可以AC,但是面试的时候题目要求可能会有这一条。 midnode.next = self.reverse(backhalf) return True diff --git a/animation-simulation/链表篇/leetcode141环形链表.md b/animation-simulation/链表篇/leetcode141环形链表.md index 20c1ce8..b0e186f 100644 --- a/animation-simulation/链表篇/leetcode141环形链表.md +++ b/animation-simulation/链表篇/leetcode141环形链表.md @@ -12,7 +12,7 @@ > 给定一个链表,判断链表中是否有环。pos代表环的入口,若为-1,则代表无环。 > -> 如果链表中存在环,则返回 true 。 否则,返回 false 。 +> 如果链表中存在环,则返回 true 。否则,返回 false 。 示例1: @@ -56,22 +56,6 @@ public class Solution { } ``` -JS Code: -```javascript -var hasCycle = function(head) { - let fast = head; - let slow = head; - while (fast && fast.next) { - fast = fast.next.next; - slow = slow.next; - if (fast === slow) { - return true; - } - } - return false; -}; -``` - C++ Code: ```cpp @@ -92,17 +76,34 @@ public: }; ``` +JS Code: + +```javascript +var hasCycle = function(head) { + let fast = head; + let slow = head; + while (fast && fast.next) { + fast = fast.next.next; + slow = slow.next; + if (fast === slow) { + return true; + } + } + return false; +}; +``` + Python Code: -```py +```python class Solution: def hasCycle(self, head: ListNode) -> bool: fast = head slow = head while fast and fast.next: fast = fast.next.next - low = low.next - if fast == low: + slow = slow.next + if fast == slow: return True return False ``` diff --git a/animation-simulation/链表篇/leetcode142环形链表2.md b/animation-simulation/链表篇/leetcode142环形链表2.md index a92a73f..e942a74 100644 --- a/animation-simulation/链表篇/leetcode142环形链表2.md +++ b/animation-simulation/链表篇/leetcode142环形链表2.md @@ -18,35 +18,7 @@ 我们可以这样假设,两个孩子在操场顺时针跑步,一个跑的快,一个跑的慢,跑的快的那个孩子总会追上跑的慢的孩子。 -环形链表: - -```java -public class Solution { - public boolean hasCycle(ListNode head) { - //特殊情况,无节点或只有一个节点的情况 - if(head == null || head.next == null){ - return false; - } - //设置快慢指针 - ListNode pro = head.next; - ListNode last = head; - //循环条件 - while( pro != null && pro.next!=null){ - pro=pro.next.next; - last=last.next; - //两指针相遇 - if(pro == last){ - return true; - } - } - //循环结束,指针没有相遇,说明没有环。相当于快指针遍历了一遍链表 - return false; - - } -} -``` - -其它语言的代码请参考[这里](https://github.com/chefyuan/algorithm-base/blob/main/animation-simulation/%E9%93%BE%E8%A1%A8%E7%AF%87/leetcode141%E7%8E%AF%E5%BD%A2%E9%93%BE%E8%A1%A8.md)。 +代码请参考[【动画模拟】leetcode 141 环形链表](https://github.com/chefyuan/algorithm-base/blob/main/animation-simulation/%E9%93%BE%E8%A1%A8%E7%AF%87/leetcode141%E7%8E%AF%E5%BD%A2%E9%93%BE%E8%A1%A8.md)。 判断链表是不是含有环很简单,但是我们想找到环的入口可能就没有那么容易了。(入口则为下图绿色节点) @@ -100,11 +72,15 @@ public: ListNode *detectCycle(ListNode *head) { if (head == nullptr) return head; if (head->next == nullptr) return head->next; + //创建新的HashSet,用于保存节点 set hash; + //遍历链表 while (head != nullptr) { + //判断哈希表中是否含有某节点,没有则保存,含有则返回该节点 if (hash.count(head)) { return head; } + //不含有,则进行保存,并移动指针 hash.insert(head); head = head->next; } @@ -137,7 +113,7 @@ var detectCycle = function(head) { Python Code: -```py +```python class Solution: def detectCycle(self, head: ListNode) -> ListNode: if head is None: @@ -253,17 +229,22 @@ JS Code: ```js var detectCycle = function(head) { + //快慢指针 let fast = head; let slow = head; + //设置循环条件 while (fast && fast.next) { fast = fast.next.next; slow = slow.next; + //相遇 if (fast == slow) { let newptr = head; + //设置一个新的指针,从头节点出发,慢指针速度为1,所以可以使用慢指针从相遇点出发 while (newptr != slow) { slow = slow.next; newptr = newptr.next; } + //在环入口相遇 return slow; } } @@ -273,7 +254,7 @@ var detectCycle = function(head) { Python Code: -```py +```python class Solution: def detectCycle(self, head: ListNode) -> ListNode: # 快慢指针 diff --git a/animation-simulation/链表篇/leetcode147对链表进行插入排序.md b/animation-simulation/链表篇/leetcode147对链表进行插入排序.md index 9df50b1..2a0b700 100644 --- a/animation-simulation/链表篇/leetcode147对链表进行插入排序.md +++ b/animation-simulation/链表篇/leetcode147对链表进行插入排序.md @@ -8,7 +8,7 @@ [【绘图解析】链表详解](https://github.com/chefyuan/algorithm-base/blob/main/animation-simulation/%E6%95%B0%E6%8D%AE%E7%BB%93%E6%9E%84%E5%92%8C%E7%AE%97%E6%B3%95/%E5%85%B3%E4%BA%8E%E9%93%BE%E8%A1%A8%E7%9A%84%E9%82%A3%E4%BA%9B%E4%BA%8B.md) -另外大家如果忘记了[【动画模拟】插入排序](https://github.com/chefyuan/algorithm-base/blob/main/animation-simulation/%E6%95%B0%E6%8D%AE%E7%BB%93%E6%9E%84%E5%92%8C%E7%AE%97%E6%B3%95/%E7%9B%B4%E6%8E%A5%E6%8F%92%E5%85%A5%E6%8E%92%E5%BA%8F.md)和[【动画模拟】归并排序](https://github.com/chefyuan/algorithm-base/blob/main/animation-simulation/%E6%95%B0%E6%8D%AE%E7%BB%93%E6%9E%84%E5%92%8C%E7%AE%97%E6%B3%95/%E5%BD%92%E5%B9%B6%E6%8E%92%E5%BA%8F.md)思想的话,可以先复习一下,不然这两道题目会看的云里雾里。 +另外大家如果忘记了[【动画模拟】插入排序](https://github.com/chefyuan/algorithm-base/blob/main/animation-simulation/%E6%95%B0%E6%8D%AE%E7%BB%93%E6%9E%84%E5%92%8C%E7%AE%97%E6%B3%95/%E7%9B%B4%E6%8E%A5%E6%8F%92%E5%85%A5%E6%8E%92%E5%BA%8F.md)和[【动画模拟】归并排序](https://github.com/chefyuan/algorithm-base/blob/main/animation-simulation/%E6%95%B0%E6%8D%AE%E7%BB%93%E6%9E%84%E5%92%8C%E7%AE%97%E6%B3%95/%E5%BD%92%E5%B9%B6%E6%8E%92%E5%BA%8F.md)思想的话,可以先复习一下,不然这两道题目会看得云里雾里。 #### [147. 对链表进行插入排序](https://leetcode-cn.com/problems/insertion-sort-list/) @@ -30,7 +30,7 @@ 我们的指针在数组时,可以随意的前后移动,将指针指向值和新元素的值比较后,将新元素插入到合适的位置。 -我们知道链表查询元素的时间复杂度为 O(n),我们只能够通过遍历链表查询元素。 +我们知道链表查询元素的时间复杂度为O(n),我们只能够通过遍历链表查询元素。 那么我们怎么才能将新元素放到合适的位置呢?见下图。 @@ -68,7 +68,7 @@ 我们想要将 3 插入到 2 和 4 的中间,此时我们三个指针分别指向 2,4,3。 -我们共分 4 步,来完成这个操作,见下图 +我们共分 4 步,来完成这个操作,见下图。 ![](https://cdn.jsdelivr.net/gh/tan45du/photobed@master/44444444.29mvcvs4yrms.png) @@ -143,9 +143,9 @@ public: continue; } //开始出发,查找新元素的合适位置 - temphead = dummyNode; + ListNode * temphead = dummyNode; while (temphead->next->val <= pre->val) { - ListNode * temphead = temphead->next; + temphead = temphead->next; } //此时我们已经找到了合适位置,我们需要进行插入,大家可以画一画 last->next = pre->next; @@ -195,7 +195,7 @@ var insertionSortList = function(head) { Python Code: -```py +```python class Solution: def insertionSortList(self, head: ListNode) -> ListNode: if head is None or head.next is None: diff --git a/animation-simulation/链表篇/leetcode206反转链表.md b/animation-simulation/链表篇/leetcode206反转链表.md index 24e60a8..5885b41 100644 --- a/animation-simulation/链表篇/leetcode206反转链表.md +++ b/animation-simulation/链表篇/leetcode206反转链表.md @@ -1,6 +1,12 @@ +> 如果阅读时,发现错误,或者动画不可以显示的问题可以添加我微信好友 **[tan45du_one](https://raw.githubusercontent.com/tan45du/tan45du.github.io/master/个人微信.15egrcgqd94w.jpg)** ,备注 github + 题目 + 问题 向我反馈 +> +> 感谢支持,该仓库会一直维护,希望对各位有一丢丢帮助。 +> +> 另外希望手机阅读的同学可以来我的 [**公众号:袁厨的算法小屋**](https://raw.githubusercontent.com/tan45du/test/master/微信图片_20210320152235.2pthdebvh1c0.png) 两个平台同步,想要和题友一起刷题,互相监督的同学,可以在我的小屋点击[**刷题小队**](https://raw.githubusercontent.com/tan45du/test/master/微信图片_20210320152235.2pthdebvh1c0.png)进入。 + 今天咱们说一道非常简单但是很经典的面试题,思路很容易,但是里面细节挺多,所以我们还是需要注意。 -我们先来看一下题目描述 +我们先来看一下题目描述。 #### [206. 反转链表](https://leetcode-cn.com/problems/reverse-linked-list/) @@ -19,9 +25,9 @@ 原理很容易理解,我们首先将 low 指针指向空节点, pro 节点指向 head 节点, -然后我们定义一个临时节点指向 pro 节点, +然后我们定义一个临时节点 temp 指向 pro 节点, -此时我们就记住了 pro 节点的位置,然后 pro = pro.next.这样我们三个指针指向三个不同的节点。 +此时我们就记住了 pro 节点的位置,然后 pro = pro.next,这样我们三个指针指向三个不同的节点。 则我们将 temp 指针指向 low 节点,此时则完成了反转。 @@ -59,29 +65,6 @@ class Solution { } } ``` -JS Code: -```javascript -var reverseList = function(head) { - //特殊情况 - if(!head || !head.next) { - return head; - } - let low = null; - let pro = head; - while (pro) { - //代表橙色指针 - let temp = pro; - //移动绿色指针 - pro = pro.next; - //反转节点 - temp.next = low; - //移动黄色指针 - low = temp; - } - return low; -}; -``` - C++ Code: ```cpp @@ -109,12 +92,36 @@ public: }; ``` +JS Code: + +```javascript +var reverseList = function(head) { + //特殊情况 + if(!head || !head.next) { + return head; + } + let low = null; + let pro = head; + while (pro) { + //代表橙色指针 + let temp = pro; + //移动绿色指针 + pro = pro.next; + //反转节点 + temp.next = low; + //移动黄色指针 + low = temp; + } + return low; +}; +``` + Python Code: -```py +```python class Solution: def reverseList(self, head: ListNode) -> ListNode: - //特殊情况 + # 特殊情况 if head is None or head.next is None: return head low = None @@ -147,8 +154,8 @@ class Solution { } //保存最后一个节点 ListNode pro = reverseList(head.next); - //将节点进行反转。我们可以这样理解 4.next.next = 4; - //4.next = 5; + //将节点进行反转。我们可以这样理解 4.next.next = 4 + //4.next = 5 //则 5.next = 4 则实现了反转 head.next.next = head; //防止循环 @@ -156,29 +163,9 @@ class Solution { return pro; } } - ``` -JS Code: -```javascript -var reverseList = function(head) { - //结束条件 - if (!head || !head.next) { - return head; - } - //保存最后一个节点 - let pro = reverseList(head.next); - //将节点进行反转。我们可以这样理解 4.next.next = 4; - //4.next = 5; - //则 5.next = 4 则实现了反转 - head.next.next = head; - //防止循环 - head.next = null; - return pro; -}; -``` - -C++代码: +C++ Code: ```cpp class Solution { @@ -190,8 +177,8 @@ public: } //保存最后一个节点 ListNode * pro = reverseList(head->next); - //将节点进行反转。我们可以这样理解 4->next->next = 4; - //4->next = 5; + //将节点进行反转。我们可以这样理解 4->next->next = 4 + //4->next = 5 //则 5->next = 4 则实现了反转 head->next->next = head; //防止循环 @@ -201,9 +188,29 @@ public: }; ``` +JS Code: + +```javascript +var reverseList = function(head) { + //结束条件 + if (!head || !head.next) { + return head; + } + //保存最后一个节点 + let pro = reverseList(head.next); + //将节点进行反转。我们可以这样理解 4.next.next = 4 + //4.next = 5 + //则 5.next = 4 则实现了反转 + head.next.next = head; + //防止循环 + head.next = null; + return pro; +}; +``` + Python Code: -```py +```python class Solution: def reverseList(self, head: ListNode) -> ListNode: # 结束条件 @@ -211,8 +218,8 @@ class Solution: return head # 保存最后一个节点 pro = self.reverseList(head.next) - # 将节点进行反转。我们可以这样理解 4->next->next = 4; - # 4->next = 5; + # 将节点进行反转。我们可以这样理解 4->next->next = 4 + # 4->next = 5 # 则 5->next = 4 则实现了反转 head.next.next = head # 防止循环 @@ -224,18 +231,18 @@ class Solution: > 贡献者[@jaredliw](https://github.com/jaredliw)注: > -> 这里提供一个比较直观的递归写法供大家参考。 +> 这里提供一个比较直观的递归写法供大家参考。由于代码比较直白,其它语言的我就不写啦。 > -> ```py +> ```python > class Solution: -> def reverseList(self, head: ListNode, prev_nd: ListNode = None) -> ListNode: -> # 结束条件 -> if head is None: -> return prev_nd -> # 记录下一个节点并反转 -> next_nd = head.next -> head.next = prev_nd -> # 给定下一组该反转的节点 -> return self.reverseList(next_nd, head) +> def reverseList(self, head: ListNode, prev_nd: ListNode = None) -> ListNode: +> # 结束条件 +> if head is None: +> return prev_nd +> # 记录下一个节点并反转 +> next_nd = head.next +> head.next = prev_nd +> # 给定下一组该反转的节点 +> return self.reverseList(next_nd, head) > ``` diff --git a/animation-simulation/链表篇/leetcode328奇偶链表.md b/animation-simulation/链表篇/leetcode328奇偶链表.md index 85bede3..1b11c0e 100644 --- a/animation-simulation/链表篇/leetcode328奇偶链表.md +++ b/animation-simulation/链表篇/leetcode328奇偶链表.md @@ -26,7 +26,7 @@ #### 题目解析 -题目也很容易理解就是让我们将原来奇数位的结点放一起,偶数位的结点放一起。这里需要注意,和结点值无关,是奇数位和偶数位结点。 +题目也很容易理解就是让我们将原来奇数位的结点放一起,偶数位的结点放一起。这里需要注意,题目和结点值无关,是奇数位和偶数位结点。 我们可以先将奇数位和在一起,再将偶数位和在一起,最后再将两个链表合并很简单,我们直接看动画模拟吧。 @@ -109,7 +109,7 @@ var oddEvenList = function(head) { Python Code: -```py +```python class Solution: def oddEvenList(self, head: ListNode) -> ListNode: if head is None or head.next is None: diff --git a/animation-simulation/链表篇/leetcode82删除排序链表中的重复元素II.md b/animation-simulation/链表篇/leetcode82删除排序链表中的重复元素II.md index 488b5b3..0768215 100644 --- a/animation-simulation/链表篇/leetcode82删除排序链表中的重复元素II.md +++ b/animation-simulation/链表篇/leetcode82删除排序链表中的重复元素II.md @@ -48,9 +48,9 @@ class Solution { public ListNode deleteDuplicates(ListNode head) { //侦察兵指针 ListNode pre = head; - //创建虚拟头节点,接上head + //创建哑节点,接上head ListNode dummy = new ListNode(-1); - dummy.next = pre; + dummy.next = head; //跟随的指针 ListNode low = dummy; while(pre != null && pre.next != null) { @@ -82,9 +82,9 @@ public: ListNode* deleteDuplicates(ListNode* head) { //侦察兵指针 ListNode * pre = head; - //创建虚拟头节点,接上head - ListNode * dummy = new ListNode(-1, head); - dummy->next = pre; + //创建哑节点,接上head + ListNode * dummy = new ListNode(-1); + dummy->next = head; //跟随的指针 ListNode * low = dummy; while(pre != nullptr && pre->next != nullptr) { @@ -141,7 +141,7 @@ var deleteDuplicates = function(head) { Python Code: -```py +```python class Solution: def deleteDuplicates(self, head: ListNode) -> ListNode: # 侦察兵指针 @@ -162,6 +162,6 @@ class Solution: else: pre = pre.next low = low.next - return low.next # 注意,这里传回的不是head,而是虚拟节点的下一个节点,head有可能已经换了 + return dummy.next # 注意,这里传回的不是head,而是虚拟节点的下一个节点,head有可能已经换了 ``` diff --git a/animation-simulation/链表篇/leetcode86分隔链表.md b/animation-simulation/链表篇/leetcode86分隔链表.md index e8e2aa9..4147a75 100644 --- a/animation-simulation/链表篇/leetcode86分隔链表.md +++ b/animation-simulation/链表篇/leetcode86分隔链表.md @@ -131,12 +131,7 @@ var partition = function(head, x) { Python Code: -```py -# Definition for singly-linked list. -# class ListNode: -# def __init__(self, val=0, next=None): -# self.val = val -# self.next = next +```python class Solution: def partition(self, head: ListNode, x: int) -> ListNode: pro = head @@ -161,3 +156,4 @@ class Solution: small.next = headbig.next return headsmall.next ``` + diff --git a/animation-simulation/链表篇/leetcode92反转链表2.md b/animation-simulation/链表篇/leetcode92反转链表2.md index 008766f..93b90b6 100644 --- a/animation-simulation/链表篇/leetcode92反转链表2.md +++ b/animation-simulation/链表篇/leetcode92反转链表2.md @@ -4,14 +4,12 @@ > > 另外希望手机阅读的同学可以来我的 [**公众号:袁厨的算法小屋**](https://raw.githubusercontent.com/tan45du/test/master/微信图片_20210320152235.2pthdebvh1c0.png) 两个平台同步,想要和题友一起刷题,互相监督的同学,可以在我的小屋点击[**刷题小队**](https://raw.githubusercontent.com/tan45du/test/master/微信图片_20210320152235.2pthdebvh1c0.png)进入。 -今天我们来说一下反转链表 2,其实这个和 1 的思路差不多,今天先说一个比较好理解的方法,完全按照反转链表 1 的方法来解决,大家看这个题目之前要先看一下[【动画模拟】leetcode 206 反转链表](https://github.com/chefyuan/algorithm-base/blob/main/animation-simulation/%E9%93%BE%E8%A1%A8%E7%AF%87/leetcode206%E5%8F%8D%E8%BD%AC%E9%93%BE%E8%A1%A8.md) +今天我们来说一下反转链表 2,其实这个和 1 的思路差不多,今天先说一个比较好理解的方法,完全按照反转链表 1 的方法来解决,大家看这个题目之前要先看一下[【动画模拟】leetcode 206 反转链表](https://github.com/chefyuan/algorithm-base/blob/main/animation-simulation/%E9%93%BE%E8%A1%A8%E7%AF%87/leetcode206%E5%8F%8D%E8%BD%AC%E9%93%BE%E8%A1%A8.md)。 下面我们先来看一下题目。 #### [92. 反转链表 II](https://leetcode-cn.com/problems/reverse-linked-list-ii/) -难度中等836 - 给你单链表的头指针 `head` 和两个整数 `left` 和 `right` ,其中 `left <= right` 。请你反转从位置 `left` 到位置 `right` 的链表节点,返回 **反转后的链表** 。 **示例 1:** @@ -166,7 +164,6 @@ var reverseBetween = function(head, left, right) { return temp.next; }; - //和反转链表1代码一致 var reverse = function(head) { let low = null; @@ -183,7 +180,7 @@ var reverse = function(head) { Python Code: -```py +```python class Solution: def reverseBetween(self, head: ListNode, left: int, right: int) -> ListNode: # 虚拟头节点 diff --git a/animation-simulation/链表篇/剑指Offer25合并两个排序的链表.md b/animation-simulation/链表篇/剑指Offer25合并两个排序的链表.md index dbf1772..cbe9b75 100644 --- a/animation-simulation/链表篇/剑指Offer25合并两个排序的链表.md +++ b/animation-simulation/链表篇/剑指Offer25合并两个排序的链表.md @@ -6,7 +6,7 @@ #### [剑指 Offer 25. 合并两个排序的链表](https://leetcode-cn.com/problems/he-bing-liang-ge-pai-xu-de-lian-biao-lcof/) -将两个升序链表合并为一个新的 升序 链表并返回。新链表是通过拼接给定的两个链表的所有节点组成的。 +将两个升序链表合并为一个新的 **升序** 链表并返回。新链表是通过拼接给定的两个链表的所有节点组成的。 示例: @@ -19,7 +19,7 @@ 迭代法: -因为我们有两个升序链表,我们需要将其合并,那么我们需要创建一个新节点headpre,然后我们利用双指针思想,每个链表放置一个指针,然后进行遍历并对比当前指针指向的值。然后headpre.next指向较小值的那个节点,不断迭代,直至到达某一有序链表底部,此时一个链表遍历完成,然后我们将未完全遍历的链表接在我们接在合并链表之后即可。 +因为我们有两个升序链表,我们需要将其合并,那么我们需要创建一个新节点 headpre,然后我们利用双指针思想,每个链表放置一个指针,然后进行遍历并对比当前指针指向的值。然后 headpre.next 指向较小值的那个节点,不断迭代,直至到达某一有序链表底部,此时一个链表遍历完成,然后我们将未完全遍历的链表接在我们接在合并链表之后即可。 这是我们迭代做法,另外这个题目还有一个递归方法,目前先不写,等链表掌握差不多的时候会单独写一篇关于递归的文章,也算是为树的题目做铺垫。 @@ -105,7 +105,7 @@ var mergeTwoLists = function(l1, l2) { Python Code: -```py +```python class Solution: def mergeTwoLists(self, l1: ListNode, l2: ListNode) -> ListNode: headpro = ListNode(-1) diff --git a/animation-simulation/链表篇/剑指Offer52两个链表的第一个公共节点.md b/animation-simulation/链表篇/剑指Offer52两个链表的第一个公共节点.md index ac9c40b..93e8ba0 100644 --- a/animation-simulation/链表篇/剑指Offer52两个链表的第一个公共节点.md +++ b/animation-simulation/链表篇/剑指Offer52两个链表的第一个公共节点.md @@ -115,7 +115,7 @@ var getIntersectionNode = function(headA, headB) { Python Code: -```py +```python class Solution: def getIntersectionNode(self, headA: ListNode, headB: ListNode) -> ListNode: tempa = headA @@ -207,7 +207,7 @@ var getIntersectionNode = function(headA, headB) { Python Code: -```py +```python class Solution: def getIntersectionNode(self, headA: ListNode, headB: ListNode) -> ListNode: # 定义两个节点 diff --git a/animation-simulation/链表篇/剑指offer22倒数第k个节点.md b/animation-simulation/链表篇/剑指offer22倒数第k个节点.md index 13224ca..5dc879c 100644 --- a/animation-simulation/链表篇/剑指offer22倒数第k个节点.md +++ b/animation-simulation/链表篇/剑指offer22倒数第k个节点.md @@ -12,13 +12,13 @@ 题目分析: -自己思考一下 +自己思考一下: 我们遇到这个题目,可能会有什么答题思路呢? 你看我说的对不对,是不是会想到先遍历一遍链表知道 链表节点的个数,然后再计算出倒数第n个节点。 -比如链表长度为10,倒数第3个节点,不就是正数第8个节点呀,这种方法当然可以啦,是可以实现的,那么我们再思考一下有没有其他方法呢?哦,对,我们可以将链表元素保存到数组里面,然后直接就可以知道倒数第K个节点了。这个方法确实比刚才那个方法省时间了,但是所耗的空间更多了,那我们还有什么方法吗? +比如链表长度为10,倒数第3个节点,不就是正数第8个节点呀,这种方法当然可以啦,是可以实现的,那么我们再思考一下有没有其他方法呢?哦,对,我们可以将链表元素保存到数组里面,然后直接就可以知道倒数第k个节点了。这个方法确实比刚才那个方法省时间了,但是所耗的空间更多了,那我们还有什么方法吗? 我们可以继续利用我们的双指针呀,但是我们应该怎么做呢? diff --git a/animation-simulation/链表篇/面试题 02.03. 链表中间节点.md b/animation-simulation/链表篇/面试题 02.03. 链表中间节点.md index b18baab..1eda138 100644 --- a/animation-simulation/链表篇/面试题 02.03. 链表中间节点.md +++ b/animation-simulation/链表篇/面试题 02.03. 链表中间节点.md @@ -6,7 +6,7 @@ #### [876. 链表的中间结点](https://leetcode-cn.com/problems/middle-of-the-linked-list/) -给定一个头结点为 head的非空单链表,返回链表的中间结点。 +给定一个头结点为 head 的非空单链表,返回链表的中间结点。 如果有两个中间结点,则返回第二个中间结点。 @@ -17,7 +17,7 @@ 输出:3 ``` -> 说明:因为只有一个中间节点 +> 说明:因为只有一个中间节点。 **示例 2:** @@ -26,9 +26,9 @@ 输出:4 ``` -> 说明:有两个中间节点所以返回后面那个 +> 说明:有两个中间节点所以返回后面那个。 -## 题目解析: +**题目解析:** 又精心筛选了一个题目,本来想写一下删除节点的题目,然后发现这个题目更符合目前的节奏,所以先写一下这个题目,明天再给大家写删除节点的题目。 @@ -44,7 +44,7 @@ 一个指针走的快,一个指针走的慢,这个题目我们可以让快指针一次走两步,慢指针一次走一步,当快指针到达链表尾部的时候,慢指针不就到达中间节点了吗? -链表中节点的个数有可能为奇数也有可能为偶数,这是两种情况,但是我们输出是相同的,那就是输出slow指针指向的节点 +链表中节点的个数有可能为奇数也有可能为偶数,这是两种情况,但是我们输出是相同的,那就是输出 slow 指针指向的节点,也就是两个中间节点的第二个。 ![在这里插入图片描述](https://img-blog.csdnimg.cn/20210321131249789.gif) @@ -105,7 +105,7 @@ var middleNode = function(head) { Python Code: -```py +```python class Solution: def middleNode(self, head: ListNode) -> ListNode: fast = head # 快指针 diff --git a/animation-simulation/链表篇/面试题 02.05. 链表求和.md b/animation-simulation/链表篇/面试题 02.05. 链表求和.md index f5e0efe..0865cb1 100644 --- a/animation-simulation/链表篇/面试题 02.05. 链表求和.md +++ b/animation-simulation/链表篇/面试题 02.05. 链表求和.md @@ -23,22 +23,22 @@ 示例1: ```java -输入:(7 -> 1 -> 6) + (5 -> 9 -> 2),即617 + 295 -输出:2 -> 1 -> 9,即912 +输入:(7 -> 1 -> 6) + (5 -> 9 -> 2),即 617 + 295 +输出:2 -> 1 -> 9,即 912 ``` 示例2: ```java -输入:(9 -> 9) + (9 -> 9),即99+99 -输出:8->9->1 +输入:(9 -> 9) + (9 -> 9),即 99 + 99 +输出:8 -> 9 -> 1 ``` 示例3: ```java -输入:(5)+(5),即5+5 -输出:0->1 +输入:(5) + (5),即 5 + 5 +输出:0 -> 1 ``` **题目解析:** @@ -67,7 +67,7 @@ ![链表求和](https://cdn.jsdelivr.net/gh/tan45du/photobed@master/photo/链表求和.1yh4ymdee3k0.gif) -注:这里需要注意得时,链表遍历结束,我们应该跳出循环,但是我们的nlist仍在尾部添加了1节点,那是因为跳出循环时,summod值为1,所以我们需要在尾部再添加一个节点。 +注:这里需要注意得时,链表遍历结束,我们应该跳出循环,但是我们的 nlist 仍在尾部添加了1节点,那是因为跳出循环时,summod 值为1,所以我们需要在尾部再添加一个节点。 @@ -79,7 +79,7 @@ Java Code: class Solution { public ListNode addTwoNumbers(ListNode l1, ListNode l2) { //待会儿要返回的链表 - ListNode nList = new ListNode(-1);//虚拟头节点 + ListNode nList = new ListNode(-1);//哑节点 ListNode tempnode = nList; //用来保存进位值,初始化为0 int summod = 0; @@ -92,7 +92,7 @@ class Solution { int sum = l1num+l2num+summod; //更新进位值,例18/10=1,9/10=0 summod = sum/10; - //新节点保存的值,18% 8=2,则添加2 + //新节点保存的值,18%8=2,则添加2 sum = sum%10; //添加节点 tempnode.next = new ListNode(sum); @@ -109,7 +109,7 @@ class Solution { if (summod != 0) { tempnode.next = new ListNode(summod); } - return nList.next;//去除-1节点 + return nList.next;//去除哑节点 } } ``` @@ -121,7 +121,7 @@ class Solution { public: ListNode* addTwoNumbers(ListNode* l1, ListNode* l2) { //待会儿要返回的链表 - ListNode * nList = new ListNode(-1);//虚拟头节点 + ListNode * nList = new ListNode(-1);//哑节点 ListNode * tempnode = nList; //用来保存进位值,初始化为0 int summod = 0; @@ -134,7 +134,7 @@ public: int sum = l1num + l2num + summod; //更新进位值,例18/10=1,9/10=0 summod = sum / 10; - //新节点保存的值,1 %8=2,则添加2 + //新节点保存的值,18%8=2,则添加2 sum = sum % 10; //添加节点 tempnode->next = new ListNode(sum); @@ -151,7 +151,7 @@ public: if (summod != 0) { tempnode->next = new ListNode(summod); } - return nList->next;//去除-1节点 + return nList->next;//哑节点 } }; ``` @@ -161,7 +161,7 @@ JS Code: ```js var addTwoNumbers = function(l1, l2) { //待会儿要返回的链表 - let nList = new ListNode(-1);//虚拟头节点 + let nList = new ListNode(-1);//哑节点 let tempnode = nList; //用来保存进位值,初始化为0 let summod = 0; @@ -174,7 +174,7 @@ var addTwoNumbers = function(l1, l2) { let sum = l1num + l2num + summod; //更新进位值,例18/10=1,9/10=0 summod = ~~(sum / 10); - //新节点保存的值,1 %8=2,则添加2 + //新节点保存的值,18%8=2,则添加2 sum = sum % 10; //添加节点 tempnode.next = new ListNode(sum); @@ -191,21 +191,21 @@ var addTwoNumbers = function(l1, l2) { if (summod !== 0) { tempnode.next = new ListNode(summod); } - return nList.next;//去除-1节点 + return nList.next;//去除哑节点 }; ``` Python Code: -```py +```python class Solution: def addTwoNumbers(self, l1: ListNode, l2: ListNode) -> ListNode: # 待会儿要返回的链表 - nList = ListNode(-1) # 虚拟头节点 + nList = ListNode(-1) # 哑节点 tempnode = nList # 用来保存进位值,初始化为0 summod = 0 - while l1 is not None and l2 is not None: + while l1 is not None o l2 is not None: # 如果l1的链表为空则l1num为0,若是不为空,则为链表的节点值 # 判断是否为空,为空就设为0 l1num = 0 if l1 is None else l1.val @@ -227,6 +227,6 @@ class Solution: # 最后根据进位值判断需不需要继续添加节点 if summod != 0: tempnode.next = ListNode(summod) - return nList.next # 去除-1节点 + return nList.next # 去除哑节点 ```