mirror of
https://github.com/chefyuan/algorithm-base.git
synced 2024-12-29 05:46:17 +00:00
Merge branch 'main' of https://github.com/chefyuan/algorithm-base
This commit is contained in:
commit
f765951ec7
@ -33,6 +33,8 @@
|
|||||||
|
|
||||||
我们首先将链表的所有元素都保存在数组中,然后再利用双指针遍历数组,进而来判断是否为回文。这个方法很容易理解,而且代码实现也比较简单。
|
我们首先将链表的所有元素都保存在数组中,然后再利用双指针遍历数组,进而来判断是否为回文。这个方法很容易理解,而且代码实现也比较简单。
|
||||||
|
|
||||||
|
**题目代码**
|
||||||
|
|
||||||
```java
|
```java
|
||||||
class Solution {
|
class Solution {
|
||||||
public boolean isPalindrome(ListNode head) {
|
public boolean isPalindrome(ListNode head) {
|
||||||
@ -72,6 +74,10 @@ class Solution {
|
|||||||
|
|
||||||
![翻转链表部分](https://cdn.jsdelivr.net/gh/tan45du/photobed@master/photo/翻转链表部分.1v2ncl72ligw.gif)
|
![翻转链表部分](https://cdn.jsdelivr.net/gh/tan45du/photobed@master/photo/翻转链表部分.1v2ncl72ligw.gif)
|
||||||
|
|
||||||
|
#### **题目代码**
|
||||||
|
|
||||||
|
Java Code:
|
||||||
|
|
||||||
```java
|
```java
|
||||||
class Solution {
|
class Solution {
|
||||||
public boolean isPalindrome(ListNode head) {
|
public boolean isPalindrome(ListNode head) {
|
||||||
@ -129,3 +135,63 @@ class Solution {
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
C++ Code:
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
class Solution {
|
||||||
|
public:
|
||||||
|
bool isPalindrome(ListNode* head) {
|
||||||
|
if (head == nullptr || head->next == nullptr) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
//找到中间节点,也就是翻转的头节点,这个在昨天的题目中讲到
|
||||||
|
//但是今天和昨天有一些不一样的地方就是,如果有两个中间节点返回第一个,昨天的题目是第二个
|
||||||
|
ListNode * midenode = searchmidnode(head);
|
||||||
|
//原地翻转链表,需要两个辅助指针。这个也是面试题目,大家可以做一下
|
||||||
|
//这里我们用的是midnode->next需要注意,因为我们找到的是中点,但是我们翻转的是后半部分
|
||||||
|
|
||||||
|
ListNode * backhalf = reverse(midenode->next);
|
||||||
|
//遍历两部分链表,判断值是否相等
|
||||||
|
ListNode * p1 = head;
|
||||||
|
ListNode * p2 = backhalf;
|
||||||
|
while (p2 != nullptr) {
|
||||||
|
if (p1->val != p2->val) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
p1 = p1->next;
|
||||||
|
p2 = p2->next;
|
||||||
|
}
|
||||||
|
// 还原链表并返回结果,这一步是需要注意的,我们不可以破坏初始结构,我们只是判断是否为回文,
|
||||||
|
//当然如果没有这一步也是可以AC,但是面试的时候题目要求可能会有这一条。
|
||||||
|
midenode->next = reverse(backhalf);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
//找到中间的部分
|
||||||
|
ListNode * searchmidnode (ListNode * head) {
|
||||||
|
ListNode * fast = new ListNode(-1);
|
||||||
|
ListNode * slow = new ListNode(-1);
|
||||||
|
fast = head;
|
||||||
|
slow = head;
|
||||||
|
//找到中点
|
||||||
|
while (fast->next != nullptr && fast->next->next != nullptr) {
|
||||||
|
fast = fast->next->next;
|
||||||
|
slow = slow->next;
|
||||||
|
}
|
||||||
|
return slow;
|
||||||
|
}
|
||||||
|
//翻转链表
|
||||||
|
ListNode * reverse (ListNode * slow) {
|
||||||
|
ListNode * low = nullptr;
|
||||||
|
ListNode * temp = nullptr;
|
||||||
|
//翻转链表
|
||||||
|
while (slow != nullptr) {
|
||||||
|
temp = slow->next;
|
||||||
|
slow->next = low;
|
||||||
|
low = slow;
|
||||||
|
slow = temp;
|
||||||
|
}
|
||||||
|
return low;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
```
|
||||||
|
|
||||||
|
@ -72,3 +72,24 @@ var hasCycle = function(head) {
|
|||||||
return false;
|
return false;
|
||||||
};
|
};
|
||||||
```
|
```
|
||||||
|
|
||||||
|
C++ Code:
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
class Solution {
|
||||||
|
public:
|
||||||
|
bool hasCycle(ListNode *head) {
|
||||||
|
ListNode * fast = head;
|
||||||
|
ListNode * low = head;
|
||||||
|
while (fast != nullptr && fast->next != nullptr) {
|
||||||
|
fast = fast->next->next;
|
||||||
|
low = low->next;
|
||||||
|
if (fast == low) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
```
|
||||||
|
|
||||||
|
@ -123,7 +123,9 @@ public class Solution {
|
|||||||
|
|
||||||
![环形链表2](https://cdn.jsdelivr.net/gh/tan45du/photobed@master/photo/环形链表2.elwu1pw2lw0.gif)
|
![环形链表2](https://cdn.jsdelivr.net/gh/tan45du/photobed@master/photo/环形链表2.elwu1pw2lw0.gif)
|
||||||
|
|
||||||
|
**题目代码**
|
||||||
|
|
||||||
|
Java Code:
|
||||||
|
|
||||||
```java
|
```java
|
||||||
public class Solution {
|
public class Solution {
|
||||||
@ -153,3 +155,34 @@ public class Solution {
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
C++ Code:
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
class Solution {
|
||||||
|
public:
|
||||||
|
ListNode *detectCycle(ListNode *head) {
|
||||||
|
//快慢指针
|
||||||
|
ListNode * fast = head;
|
||||||
|
ListNode * low = head;
|
||||||
|
//设置循环条件
|
||||||
|
while (fast != nullptr && fast->next != nullptr) {
|
||||||
|
fast = fast->next->next;
|
||||||
|
low = low->next;
|
||||||
|
//相遇
|
||||||
|
if (fast == low) {
|
||||||
|
//设置一个新的指针,从头节点出发,慢指针速度为1,所以可以使用慢指针从相遇点出发
|
||||||
|
ListNode * newnode = head;
|
||||||
|
while (newnode != low) {
|
||||||
|
low = low->next;
|
||||||
|
newnode = newnode->next;
|
||||||
|
}
|
||||||
|
//在环入口相遇
|
||||||
|
return low;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nullptr;
|
||||||
|
|
||||||
|
}
|
||||||
|
};
|
||||||
|
```
|
||||||
|
|
||||||
|
@ -82,6 +82,8 @@
|
|||||||
|
|
||||||
**题目代码**
|
**题目代码**
|
||||||
|
|
||||||
|
Java Code:
|
||||||
|
|
||||||
```java
|
```java
|
||||||
class Solution {
|
class Solution {
|
||||||
public ListNode insertionSortList(ListNode head) {
|
public ListNode insertionSortList(ListNode head) {
|
||||||
@ -121,7 +123,45 @@ class Solution {
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
C++ Code:
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
class Solution {
|
||||||
|
public:
|
||||||
|
ListNode* insertionSortList(ListNode* head) {
|
||||||
|
if (head == nullptr && head->next == nullptr) {
|
||||||
|
return head;
|
||||||
|
}
|
||||||
|
//哑节点
|
||||||
|
ListNode * dummyNode = new ListNode(-1);
|
||||||
|
dummyNode->next = head;
|
||||||
|
//pre负责指向新元素,last 负责指向新元素的前一元素
|
||||||
|
//判断是否需要执行插入操作
|
||||||
|
ListNode * pre = head->next;
|
||||||
|
ListNode * last = head;
|
||||||
|
ListNode * temphead = dummyNode;
|
||||||
|
while (pre != nullptr) {
|
||||||
|
//不需要插入到合适位置,则继续往下移动
|
||||||
|
if (last->val <= pre->val) {
|
||||||
|
pre = pre->next;
|
||||||
|
last = last->next;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
//开始出发,查找新元素的合适位置
|
||||||
|
temphead = dummyNode;
|
||||||
|
while (temphead->next->val <= pre->val) {
|
||||||
|
temphead = temphead->next;
|
||||||
|
}
|
||||||
|
//此时我们已经找到了合适位置,我们需要进行插入,大家可以画一画
|
||||||
|
last->next = pre->next;
|
||||||
|
pre->next = temphead->next;
|
||||||
|
temphead->next = pre;
|
||||||
|
pre = last->next;
|
||||||
|
}
|
||||||
|
return dummyNode->next;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -33,6 +33,10 @@ low = temp 即可。然后重复执行上诉操作直至最后,这样则完成
|
|||||||
|
|
||||||
我会对每个关键点进行注释,大家可以参考动图理解。
|
我会对每个关键点进行注释,大家可以参考动图理解。
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
**题目代码**
|
||||||
|
|
||||||
Java Code:
|
Java Code:
|
||||||
```java
|
```java
|
||||||
class Solution {
|
class Solution {
|
||||||
@ -81,8 +85,44 @@ var reverseList = function(head) {
|
|||||||
};
|
};
|
||||||
```
|
```
|
||||||
|
|
||||||
|
C++代码
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
class Solution {
|
||||||
|
public:
|
||||||
|
ListNode* reverseList(ListNode* head) {
|
||||||
|
//特殊情况
|
||||||
|
if (head == nullptr || head->next == nullptr) {
|
||||||
|
return head;
|
||||||
|
}
|
||||||
|
//反转
|
||||||
|
return reverse(head);
|
||||||
|
}
|
||||||
|
ListNode * reverse (ListNode * head) {
|
||||||
|
|
||||||
|
ListNode * low = nullptr;
|
||||||
|
ListNode * pro = head;
|
||||||
|
while (pro != nullptr) {
|
||||||
|
//代表橙色指针
|
||||||
|
ListNode * temp = pro;
|
||||||
|
//移动绿色指针
|
||||||
|
pro = pro->next;
|
||||||
|
//反转节点
|
||||||
|
temp->next = low;
|
||||||
|
//移动黄色指针
|
||||||
|
low = temp;
|
||||||
|
}
|
||||||
|
return low;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
```
|
||||||
|
|
||||||
上面的迭代写法是不是搞懂啦,现在还有一种递归写法,不是特别容易理解,刚开始刷题的同学,可以只看迭代解法。
|
上面的迭代写法是不是搞懂啦,现在还有一种递归写法,不是特别容易理解,刚开始刷题的同学,可以只看迭代解法。
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
**题目代码**
|
||||||
|
|
||||||
Java Code:
|
Java Code:
|
||||||
```java
|
```java
|
||||||
class Solution {
|
class Solution {
|
||||||
@ -118,3 +158,26 @@ var reverseList = function(head) {
|
|||||||
};
|
};
|
||||||
```
|
```
|
||||||
|
|
||||||
|
C++代码:
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
class Solution {
|
||||||
|
public:
|
||||||
|
ListNode * reverseList(ListNode * head) {
|
||||||
|
//结束条件
|
||||||
|
if (head == nullptr || head->next == nullptr) {
|
||||||
|
return head;
|
||||||
|
}
|
||||||
|
//保存最后一个节点
|
||||||
|
ListNode * pro = reverseList(head->next);
|
||||||
|
//将节点进行反转。我们可以这样理解 4->next->next = 4;
|
||||||
|
//4->next = 5;
|
||||||
|
//则 5->next = 4 则实现了反转
|
||||||
|
head->next->next = head;
|
||||||
|
//防止循环
|
||||||
|
head->next = nullptr;
|
||||||
|
return pro;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
```
|
||||||
|
|
||||||
|
@ -36,6 +36,8 @@
|
|||||||
|
|
||||||
#### 题目代码
|
#### 题目代码
|
||||||
|
|
||||||
|
Java Code:
|
||||||
|
|
||||||
```java
|
```java
|
||||||
class Solution {
|
class Solution {
|
||||||
public ListNode oddEvenList(ListNode head) {
|
public ListNode oddEvenList(ListNode head) {
|
||||||
@ -60,3 +62,30 @@ class Solution {
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
C++ Code:
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
class Solution {
|
||||||
|
public:
|
||||||
|
ListNode* oddEvenList(ListNode* head) {
|
||||||
|
if (head == nullptr || head->next == nullptr) {
|
||||||
|
return head;
|
||||||
|
}
|
||||||
|
ListNode * odd = head;
|
||||||
|
ListNode * even = head->next;
|
||||||
|
ListNode * evenhead = even;
|
||||||
|
|
||||||
|
while (odd->next != nullptr && even->next != nullptr) {
|
||||||
|
//将偶数位合在一起,奇数位合在一起
|
||||||
|
odd->next = even->next;
|
||||||
|
odd = odd->next;
|
||||||
|
even->next = odd->next;
|
||||||
|
even = even->next;
|
||||||
|
}
|
||||||
|
//链接
|
||||||
|
odd->next = evenhead;
|
||||||
|
return head;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
```
|
||||||
|
|
||||||
|
@ -39,6 +39,10 @@
|
|||||||
|
|
||||||
![删除重复节点2](https://cdn.jsdelivr.net/gh/tan45du/photobed@master/photo/删除重复节点2.3btmii5cgxa0.gif)
|
![删除重复节点2](https://cdn.jsdelivr.net/gh/tan45du/photobed@master/photo/删除重复节点2.3btmii5cgxa0.gif)
|
||||||
|
|
||||||
|
**题目代码**
|
||||||
|
|
||||||
|
Java Code:
|
||||||
|
|
||||||
```java
|
```java
|
||||||
class Solution {
|
class Solution {
|
||||||
public ListNode deleteDuplicates(ListNode head) {
|
public ListNode deleteDuplicates(ListNode head) {
|
||||||
@ -68,3 +72,35 @@ class Solution {
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
C++ Code:
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
class Solution {
|
||||||
|
public:
|
||||||
|
ListNode* deleteDuplicates(ListNode* head) {
|
||||||
|
if(head == nullptr || head->next == nullptr){
|
||||||
|
return head;
|
||||||
|
}
|
||||||
|
ListNode * pre = head;
|
||||||
|
ListNode * low = new ListNode(0);
|
||||||
|
low->next = pre;
|
||||||
|
ListNode * ret = new ListNode(-1);
|
||||||
|
ret = low;
|
||||||
|
while(pre != nullptr && pre->next != nullptr) {
|
||||||
|
if (pre->val == pre->next->val) {
|
||||||
|
while (pre != nullptr && pre->next != nullptr && pre->val == pre->next->val) {
|
||||||
|
pre = pre->next;
|
||||||
|
}
|
||||||
|
pre = pre->next;
|
||||||
|
low->next = pre;
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
pre = pre->next;
|
||||||
|
low = low->next;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return ret->next;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
```
|
||||||
|
|
||||||
|
@ -34,6 +34,8 @@
|
|||||||
|
|
||||||
**题目代码**
|
**题目代码**
|
||||||
|
|
||||||
|
Java Code:
|
||||||
|
|
||||||
```java
|
```java
|
||||||
/**
|
/**
|
||||||
* Definition for singly-linked list.
|
* Definition for singly-linked list.
|
||||||
@ -75,7 +77,41 @@ class Solution {
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
C++ Code:
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
class Solution {
|
||||||
|
public:
|
||||||
|
ListNode* partition(ListNode* head, int x) {
|
||||||
|
if (head == nullptr) {
|
||||||
|
return head;
|
||||||
|
}
|
||||||
|
ListNode * pro = head;
|
||||||
|
ListNode * big = new ListNode(-1);
|
||||||
|
ListNode * small = new ListNode(-1);
|
||||||
|
ListNode * headbig = big;
|
||||||
|
ListNode * headsmall =small;
|
||||||
|
//分
|
||||||
|
while (pro != nullptr) {
|
||||||
|
//大于时,放到 big 链表上
|
||||||
|
if (pro->val >= x) {
|
||||||
|
big->next = pro;
|
||||||
|
big = big->next;
|
||||||
|
// 小于放到 small 链表上
|
||||||
|
}else {
|
||||||
|
small->next = pro;
|
||||||
|
small = small->next;
|
||||||
|
}
|
||||||
|
pro = pro->next;
|
||||||
|
}
|
||||||
|
//细节
|
||||||
|
big->next = nullptr;
|
||||||
|
//合
|
||||||
|
small->next = headbig->next;
|
||||||
|
return headsmall->next;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -34,6 +34,12 @@
|
|||||||
|
|
||||||
是不是很容易理解,下面我们来看代码吧。
|
是不是很容易理解,下面我们来看代码吧。
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
**题目代码**
|
||||||
|
|
||||||
|
Java Code:
|
||||||
|
|
||||||
```java
|
```java
|
||||||
class Solution {
|
class Solution {
|
||||||
public ListNode reverseBetween(ListNode head, int left, int right) {
|
public ListNode reverseBetween(ListNode head, int left, int right) {
|
||||||
@ -79,3 +85,47 @@ class Solution {
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
C++ Code:
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
class Solution {
|
||||||
|
public:
|
||||||
|
ListNode* reverseBetween(ListNode* head, int left, int right) {
|
||||||
|
ListNode * temp = new ListNode(-1);
|
||||||
|
temp->next = head;
|
||||||
|
ListNode * pro = temp;
|
||||||
|
//来到 left 节点前的一个节点
|
||||||
|
int i = 0;
|
||||||
|
for (; i < left-1; ++i) {
|
||||||
|
pro = pro->next;
|
||||||
|
}
|
||||||
|
// 保存 left 节点前的第一个节点
|
||||||
|
ListNode * leftNode = pro;
|
||||||
|
for (; i < right; ++i) {
|
||||||
|
pro = pro->next;
|
||||||
|
}
|
||||||
|
// 保存 right 节点后的节点
|
||||||
|
ListNode * rightNode = pro->next;
|
||||||
|
//切断链表
|
||||||
|
pro->next = nullptr;
|
||||||
|
ListNode * newhead = leftNode->next;
|
||||||
|
leftNode->next = nullptr;
|
||||||
|
leftNode->next = rever(newhead);
|
||||||
|
//重新接头
|
||||||
|
newhead->next = rightNode;
|
||||||
|
return temp->next;
|
||||||
|
}
|
||||||
|
ListNode * rever (ListNode * head) {
|
||||||
|
ListNode * low = nullptr;
|
||||||
|
ListNode * pro = head;
|
||||||
|
while (pro != nullptr) {
|
||||||
|
ListNode * temp = pro;
|
||||||
|
pro = pro->next;
|
||||||
|
temp->next = low;
|
||||||
|
low = temp;
|
||||||
|
}
|
||||||
|
return low;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
```
|
||||||
|
|
||||||
|
@ -26,14 +26,18 @@
|
|||||||
|
|
||||||
### HashSet
|
### HashSet
|
||||||
|
|
||||||
这个方法是比较简单的,主要思路就是,先遍历一个链表将链表的所有值都存到哈希表中,然后再遍历另一个链表,如果发现某个结点在哈希表中已经存在那我们直接返回该节点即可,代码也很简单。
|
这个方法是比较简单的,主要思路就是,先遍历一个链表将链表的所有值都存到Hashset中,然后再遍历另一个链表,如果发现某个结点在Hashset中已经存在那我们直接返回该节点即可,代码也很简单。
|
||||||
|
|
||||||
|
**题目代码**
|
||||||
|
|
||||||
|
Java Code:
|
||||||
|
|
||||||
```java
|
```java
|
||||||
public class Solution {
|
public class Solution {
|
||||||
public ListNode getIntersectionNode (ListNode headA, ListNode headB) {
|
public ListNode getIntersectionNode (ListNode headA, ListNode headB) {
|
||||||
ListNode tempa = headA;
|
ListNode tempa = headA;
|
||||||
ListNode tempb = headB;
|
ListNode tempb = headB;
|
||||||
//定义hash表
|
//定义Hashset
|
||||||
HashSet<ListNode> arr = new HashSet<ListNode>();
|
HashSet<ListNode> arr = new HashSet<ListNode>();
|
||||||
while (tempa != null) {
|
while (tempa != null) {
|
||||||
arr.add(tempa);
|
arr.add(tempa);
|
||||||
@ -46,11 +50,35 @@ public class Solution {
|
|||||||
tempb = tempb.next;
|
tempb = tempb.next;
|
||||||
}
|
}
|
||||||
return tempb;
|
return tempb;
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
C++ Code:
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
class Solution {
|
||||||
|
public:
|
||||||
|
ListNode *getIntersectionNode(ListNode *headA, ListNode *headB) {
|
||||||
|
ListNode * tempa = headA;
|
||||||
|
ListNode * tempb = headB;
|
||||||
|
//定义Hashset, cpp对应set
|
||||||
|
set <ListNode *> arr;
|
||||||
|
while (tempa != nullptr) {
|
||||||
|
arr.insert(tempa);
|
||||||
|
tempa = tempa->next;
|
||||||
|
}
|
||||||
|
while (tempb != nullptr) {
|
||||||
|
if (arr.find(tempb) != arr.end()) {
|
||||||
|
return tempb;
|
||||||
|
}
|
||||||
|
tempb = tempb->next;
|
||||||
|
}
|
||||||
|
return tempb;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
```
|
||||||
|
|
||||||
下面这个方法比较巧妙,不是特别容易想到,大家可以自己实现一下,这个方法也是利用我们的双指针思想。
|
下面这个方法比较巧妙,不是特别容易想到,大家可以自己实现一下,这个方法也是利用我们的双指针思想。
|
||||||
|
|
||||||
下面我们直接看动图吧,特别直观,一下就可以搞懂。
|
下面我们直接看动图吧,特别直观,一下就可以搞懂。
|
||||||
@ -59,6 +87,10 @@ public class Solution {
|
|||||||
|
|
||||||
是不是一下就懂了呀,我们利用双指针,当某一指针遍历完链表之后,然后掉头去另一个链表的头部,继续遍历。因为速度相同所以他们第二次遍历的时候肯定会相遇,是不是很浪漫啊!
|
是不是一下就懂了呀,我们利用双指针,当某一指针遍历完链表之后,然后掉头去另一个链表的头部,继续遍历。因为速度相同所以他们第二次遍历的时候肯定会相遇,是不是很浪漫啊!
|
||||||
|
|
||||||
|
**题目代码**
|
||||||
|
|
||||||
|
Java Code:
|
||||||
|
|
||||||
```java
|
```java
|
||||||
public class Solution {
|
public class Solution {
|
||||||
public ListNode getIntersectionNode (ListNode headA, ListNode headB) {
|
public ListNode getIntersectionNode (ListNode headA, ListNode headB) {
|
||||||
@ -76,7 +108,25 @@ public class Solution {
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
C++ Code:
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
class Solution {
|
||||||
|
public:
|
||||||
|
ListNode *getIntersectionNode(ListNode *headA, ListNode *headB) {
|
||||||
|
//定义两个节点
|
||||||
|
ListNode * tempa = headA;
|
||||||
|
ListNode * tempb = headB;
|
||||||
|
//循环
|
||||||
|
while (tempa != tempb) {
|
||||||
|
//如果不为空就指针下移,为空就跳到另一链表的头部
|
||||||
|
tempa = tempa != nullptr ? tempa->next: headB;
|
||||||
|
tempb = tempb != nullptr ? tempb->next: headA;
|
||||||
|
}
|
||||||
|
return tempa;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
```
|
||||||
|
|
||||||
好啦,链表的题目就结束啦,希望大家能有所收获,下周就要更新新的题型啦,继续坚持,肯定会有收获的。
|
好啦,链表的题目就结束啦,希望大家能有所收获,下周就要更新新的题型啦,继续坚持,肯定会有收获的。
|
||||||
|
|
||||||
|
@ -27,7 +27,12 @@
|
|||||||
|
|
||||||
![合并数组](https://cdn.jsdelivr.net/gh/tan45du/photobed@master/photo/合并数组.216f4nn4lti8.gif)
|
![合并数组](https://cdn.jsdelivr.net/gh/tan45du/photobed@master/photo/合并数组.216f4nn4lti8.gif)
|
||||||
|
|
||||||
|
**题目代码**
|
||||||
|
|
||||||
|
Java Code:
|
||||||
|
|
||||||
```java
|
```java
|
||||||
|
class Solution {
|
||||||
public ListNode mergeTwoLists(ListNode l1, ListNode l2) {
|
public ListNode mergeTwoLists(ListNode l1, ListNode l2) {
|
||||||
ListNode headpro = new ListNode(-1);
|
ListNode headpro = new ListNode(-1);
|
||||||
ListNode headtemp = headpro;
|
ListNode headtemp = headpro;
|
||||||
@ -45,7 +50,33 @@
|
|||||||
}
|
}
|
||||||
headpro.next = l1 != null ? l1:l2;
|
headpro.next = l1 != null ? l1:l2;
|
||||||
return headtemp.next;
|
return headtemp.next;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
C++ Code:
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
class Solution {
|
||||||
|
public:
|
||||||
|
ListNode* mergeTwoLists(ListNode* l1, ListNode* l2) {
|
||||||
|
ListNode * headpro = new ListNode(-1);
|
||||||
|
ListNode * headtemp = headpro;
|
||||||
|
while (l1 != nullptr && l2 != nullptr) {
|
||||||
|
//接上大的那个
|
||||||
|
if (l1->val >= l2->val) {
|
||||||
|
headpro->next = l2;
|
||||||
|
l2 = l2->next;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
headpro->next = l1;
|
||||||
|
l1 = l1->next;
|
||||||
|
}
|
||||||
|
headpro = headpro->next;
|
||||||
|
}
|
||||||
|
headpro->next = l1 != nullptr ? l1: l2;
|
||||||
|
return headtemp->next;
|
||||||
|
}
|
||||||
|
};
|
||||||
```
|
```
|
||||||
|
|
||||||
|
@ -26,14 +26,20 @@
|
|||||||
|
|
||||||
### HashSet
|
### HashSet
|
||||||
|
|
||||||
这个方法是比较简单的,主要思路就是,先遍历一个链表将链表的所有值都存到哈希表中,然后再遍历另一个链表,如果发现某个结点在哈希表中已经存在那我们直接返回该节点即可,代码也很简单。
|
这个方法是比较简单的,主要思路就是,先遍历一个链表将链表的所有值都存到Hashset中,然后再遍历另一个链表,如果发现某个结点在Hashset中已经存在那我们直接返回该节点即可,代码也很简单。
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
**题目代码**
|
||||||
|
|
||||||
|
Java Code:
|
||||||
|
|
||||||
```java
|
```java
|
||||||
public class Solution {
|
public class Solution {
|
||||||
public ListNode getIntersectionNode (ListNode headA, ListNode headB) {
|
public ListNode getIntersectionNode (ListNode headA, ListNode headB) {
|
||||||
ListNode tempa = headA;
|
ListNode tempa = headA;
|
||||||
ListNode tempb = headB;
|
ListNode tempb = headB;
|
||||||
//定义hash表
|
//定义Hashset
|
||||||
HashSet<ListNode> arr = new HashSet<ListNode>();
|
HashSet<ListNode> arr = new HashSet<ListNode>();
|
||||||
while (tempa != null) {
|
while (tempa != null) {
|
||||||
arr.add(tempa);
|
arr.add(tempa);
|
||||||
@ -51,6 +57,31 @@ public class Solution {
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
C++ Code:
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
class Solution {
|
||||||
|
public:
|
||||||
|
ListNode * getIntersectionNode(ListNode *headA, ListNode *headB) {
|
||||||
|
ListNode * tempa = headA;
|
||||||
|
ListNode * tempb = headB;
|
||||||
|
//定义Hashset
|
||||||
|
set <ListNode *> arr;
|
||||||
|
while (tempa != nullptr) {
|
||||||
|
arr.insert(tempa);
|
||||||
|
tempa = tempa->next;
|
||||||
|
}
|
||||||
|
while (tempb != nullptr) {
|
||||||
|
if (arr.find(tempb) != arr.end()) {
|
||||||
|
return tempb;
|
||||||
|
}
|
||||||
|
tempb = tempb->next;
|
||||||
|
}
|
||||||
|
return tempb;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
```
|
||||||
|
|
||||||
下面这个方法比较巧妙,不是特别容易想到,大家可以自己实现一下,这个方法也是利用我们的双指针思想。
|
下面这个方法比较巧妙,不是特别容易想到,大家可以自己实现一下,这个方法也是利用我们的双指针思想。
|
||||||
|
|
||||||
下面我们直接看动图吧,特别直观,一下就可以搞懂。
|
下面我们直接看动图吧,特别直观,一下就可以搞懂。
|
||||||
@ -59,6 +90,12 @@ public class Solution {
|
|||||||
|
|
||||||
是不是一下就懂了呀,我们利用双指针,当某一指针遍历完链表之后,然后掉头去另一个链表的头部,继续遍历。因为速度相同所以他们第二次遍历的时候肯定会相遇,是不是很浪漫啊!
|
是不是一下就懂了呀,我们利用双指针,当某一指针遍历完链表之后,然后掉头去另一个链表的头部,继续遍历。因为速度相同所以他们第二次遍历的时候肯定会相遇,是不是很浪漫啊!
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
**题目代码**
|
||||||
|
|
||||||
|
Java Code:
|
||||||
|
|
||||||
```java
|
```java
|
||||||
public class Solution {
|
public class Solution {
|
||||||
public ListNode getIntersectionNode (ListNode headA, ListNode headB) {
|
public ListNode getIntersectionNode (ListNode headA, ListNode headB) {
|
||||||
@ -68,15 +105,33 @@ public class Solution {
|
|||||||
//循环
|
//循环
|
||||||
while (tempa != tempb) {
|
while (tempa != tempb) {
|
||||||
//如果不为空就指针下移,为空就跳到另一链表的头部
|
//如果不为空就指针下移,为空就跳到另一链表的头部
|
||||||
tempa = tempa!=null ? tempa.next:headB;
|
tempa = tempa != null ? tempa.next: headB;
|
||||||
tempb = tempb!=null ? tempb.next:headA;
|
tempb = tempb != null ? tempb.next: headA;
|
||||||
}
|
}
|
||||||
return tempa;
|
return tempa;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
C++ Code:
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
class Solution {
|
||||||
|
public:
|
||||||
|
ListNode * getIntersectionNode(ListNode *headA, ListNode *headB) {
|
||||||
|
//定义两个节点
|
||||||
|
ListNode * tempa = headA;
|
||||||
|
ListNode * tempb = headB;
|
||||||
|
//循环
|
||||||
|
while (tempa != tempb) {
|
||||||
|
//如果不为空就指针下移,为空就跳到另一链表的头部
|
||||||
|
tempa = tempa != nullptr ? tempa->next: headB;
|
||||||
|
tempb = tempb != nullptr ? tempb->next: headA;
|
||||||
|
}
|
||||||
|
return tempa;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
```
|
||||||
|
|
||||||
好啦,链表的题目就结束啦,希望大家能有所收获,下周就要更新新的题型啦,继续坚持,肯定会有收获的。
|
好啦,链表的题目就结束啦,希望大家能有所收获,下周就要更新新的题型啦,继续坚持,肯定会有收获的。
|
||||||
|
|
||||||
|
@ -30,6 +30,10 @@
|
|||||||
|
|
||||||
感觉这个方法既巧妙又简单,大家可以自己动手打一下,这个题目是经典题目。
|
感觉这个方法既巧妙又简单,大家可以自己动手打一下,这个题目是经典题目。
|
||||||
|
|
||||||
|
**题目代码**
|
||||||
|
|
||||||
|
Java Code:
|
||||||
|
|
||||||
```java
|
```java
|
||||||
class Solution {
|
class Solution {
|
||||||
public ListNode getKthFromEnd (ListNode head, int k) {
|
public ListNode getKthFromEnd (ListNode head, int k) {
|
||||||
@ -58,3 +62,34 @@ class Solution {
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
C++ Code:
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
class Solution {
|
||||||
|
public:
|
||||||
|
ListNode * getKthFromEnd(ListNode * head, int k) {
|
||||||
|
//特殊情况
|
||||||
|
if (head == nullptr) {
|
||||||
|
return head;
|
||||||
|
}
|
||||||
|
//初始化两个指针
|
||||||
|
ListNode * pro = new ListNode(-1);
|
||||||
|
ListNode * after = new ListNode(-1);
|
||||||
|
//定义指针指向
|
||||||
|
pro = head;
|
||||||
|
after = head;
|
||||||
|
//先移动绿指针到指定位置
|
||||||
|
for (int i = 0; i < k-1; i++) {
|
||||||
|
pro = pro->next;
|
||||||
|
}
|
||||||
|
//两个指针同时移动
|
||||||
|
while (pro->next != nullptr) {
|
||||||
|
pro = pro->next;
|
||||||
|
after = after->next;
|
||||||
|
}
|
||||||
|
//返回倒数第k个节点
|
||||||
|
return after;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
```
|
||||||
|
|
||||||
|
@ -48,6 +48,10 @@
|
|||||||
|
|
||||||
![在这里插入图片描述](https://img-blog.csdnimg.cn/20210321131249789.gif)
|
![在这里插入图片描述](https://img-blog.csdnimg.cn/20210321131249789.gif)
|
||||||
|
|
||||||
|
**题目代码**
|
||||||
|
|
||||||
|
Java Code:
|
||||||
|
|
||||||
```java
|
```java
|
||||||
class Solution {
|
class Solution {
|
||||||
public ListNode middleNode(ListNode head) {
|
public ListNode middleNode(ListNode head) {
|
||||||
@ -64,3 +68,21 @@ class Solution {
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
C++ Code:
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
public:
|
||||||
|
ListNode* middleNode(ListNode* head) {
|
||||||
|
ListNode * fast = head;//快指针
|
||||||
|
ListNode * slow = head;//慢指针
|
||||||
|
//循环条件,思考一下跳出循环的情况
|
||||||
|
while (fast != nullptr && fast->next != nullptr) {
|
||||||
|
fast = fast->next->next;
|
||||||
|
slow = slow->next;
|
||||||
|
}
|
||||||
|
//返回slow指针指向的节点
|
||||||
|
return slow;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
```
|
||||||
|
|
||||||
|
@ -69,6 +69,12 @@
|
|||||||
|
|
||||||
注:这里需要注意得时,链表遍历结束,我们应该跳出循环,但是我们的nlist仍在尾部添加了1节点,那是因为跳出循环时,summod值为1,所以我们需要在尾部再添加一个节点。
|
注:这里需要注意得时,链表遍历结束,我们应该跳出循环,但是我们的nlist仍在尾部添加了1节点,那是因为跳出循环时,summod值为1,所以我们需要在尾部再添加一个节点。
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
**题目代码**
|
||||||
|
|
||||||
|
Java Code:
|
||||||
|
|
||||||
```java
|
```java
|
||||||
class Solution {
|
class Solution {
|
||||||
public ListNode addTwoNumbers(ListNode l1, ListNode l2) {
|
public ListNode addTwoNumbers(ListNode l1, ListNode l2) {
|
||||||
@ -108,3 +114,45 @@ class Solution {
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
C++ Code:
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
class Solution {
|
||||||
|
public:
|
||||||
|
ListNode* addTwoNumbers(ListNode* l1, ListNode* l2) {
|
||||||
|
//返回链表
|
||||||
|
ListNode * nList = new ListNode(-1);
|
||||||
|
ListNode * tempnode = nList;
|
||||||
|
//用来保存进位值,初始化为0
|
||||||
|
int summod = 0;
|
||||||
|
while(l1 != nullptr || l2 != nullptr) {
|
||||||
|
//如果l1的链表为空则l1num为0,若是不为空,则为链表的节点值
|
||||||
|
//判断是否为空,为空就设为0
|
||||||
|
int l1num = l1 == nullptr ? 0 : l1->val;
|
||||||
|
int l2num = l2 == nullptr ? 0 : l2->val;
|
||||||
|
//将链表的值和进位值相加,得到为返回链表的值
|
||||||
|
int sum = l1num + l2num + summod;
|
||||||
|
//更新进位值,例18/10=1,9/10=0
|
||||||
|
summod = sum / 10;
|
||||||
|
//新节点保存的值,18 % 8=2,则添加2
|
||||||
|
sum = sum % 10;
|
||||||
|
//添加节点
|
||||||
|
tempnode->next = new ListNode(sum);
|
||||||
|
//移动指针
|
||||||
|
tempnode = tempnode->next;
|
||||||
|
if (l1 != nullptr) {
|
||||||
|
l1 = l1->next;
|
||||||
|
}
|
||||||
|
if (l2 != nullptr) {
|
||||||
|
l2 = l2->next;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//最后根据进位值判断需不需要继续添加节点
|
||||||
|
if (summod == 1) {
|
||||||
|
tempnode->next = new ListNode(summod);
|
||||||
|
}
|
||||||
|
return nList->next;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
```
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user