8.13 刷题记录
- 6. 反转链表
- 方法一: 迭代
- 方法二:递归
- 7. 合并两个排序的链表
- 8. 复杂链表的复刻
- 9. 二叉搜索树与双向链表
6. 反转链表
原题链接
方法一: 迭代
1 -> 2 -> 3 -> 4
i j
1 <- 2 -> 3 -> 4
i j
就像这样迭代
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode(int x) : val(x), next(NULL) {}
* };
*/
class Solution {
public:
ListNode* reverseList(ListNode* head) {
ListNode *prev = nullptr;
ListNode *cur = head;
while (cur)
{
ListNode *next = cur->next;
cur->next = prev;
prev = cur, cur = next;
}
return prev;
}
};
方法二:递归
1->2->3->4
因为用递归,翻转顺序指定是
从后往前
但是注意的是,返回的值应该是头节点,也就是4的值
那么如何递归?
- 接收返回值
- 递归当前两个节点
- 返回返回值
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode(int x) : val(x), next(NULL) {}
* };
*/
class Solution {
public:
ListNode* reverseList(ListNode* head) {
if (!head || !head->next) return head;
ListNode *tail = reverseList(head->next);
head->next->next = head;
head->next = nullptr;
return tail;
}
};
/**
* Definition for singly-linked list.
* public class ListNode {
* int val;
* ListNode next;
* ListNode(int x) { val = x; }
* }
*/
class Solution {
public ListNode reverseList(ListNode head) {
if(head == null)
return null;
ListNode l = head.next;
head.next = null;
while(l != null){
ListNode ll = l.next;
l.next = head;
head = l;
l = ll;
}
return head;
}
}
7. 合并两个排序的链表
原题链接
定义一个头节点,然后定义一个链表cur指向辅助
主要是完成
直接在两个表上的链路连接
比如 1->3 2->4合并
因为1小于2
那么直接让1->2(前提 l1的角标已经移到3)
如图
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode(int x) : val(x), next(NULL) {}
* };
*/
class Solution {
public:
ListNode* merge(ListNode* l1, ListNode* l2) {
ListNode *dummy = new ListNode(0);
ListNode *cur = dummy;
while (l1 != NULL && l2 != NULL) {
if (l1 -> val < l2 -> val) {
cur -> next = l1;
l1 = l1 -> next;
}
else {
cur -> next = l2;
l2 = l2 -> next;
}
cur = cur -> next;
}
cur -> next = (l1 != NULL ? l1 : l2);
return dummy -> next;
}
};
/**
* Definition for singly-linked list.
* public class ListNode {
* int val;
* ListNode next;
* ListNode(int x) { val = x; }
* }
*/
class Solution {
public ListNode merge(ListNode l1, ListNode l2) {
// 1. 先判空
if(l1 == null) return l2;
if(l2 == null) return l1;
// 2. 创建头节点 便于返回答案
ListNode Head = new ListNode(0);
ListNode cur = Head;
while(l1 != null && l2 != null){
ListNode p1 = l1.next;
ListNode p2 = l2.next;
if(l1.val <= l2.val){
cur.next = l1;
l1 = p1;
} else {
cur.next = l2;
l2 = p2;
}
cur = cur.next;
}
if(l1 == null && l2 != null)
cur.next = l2;
if(l1 != null && l2 == null)
cur.next = l1;
return Head.next;
}
}
8. 复杂链表的复刻
原题链接
/**
* Definition for singly-linked list with a random pointer.
* struct ListNode {
* int val;
* ListNode *next, *random;
* ListNode(int x) : val(x), next(NULL), random(NULL) {}
* };
*/
class Solution {
public:
ListNode *copyRandomList(ListNode *head) {
for(auto p = head; p ; ) //遍历原链表
{
auto np = new ListNode(p->val); //复刻节点
auto next = p->next; //留存原链表当前节点p的下一个节点
p->next = np;//将原链表当前节点p指向复刻节点
np->next = next;//复刻节点np指向原链表当前节点的下一个节点
p = next; //p指针后移
}
for (auto p = head; p; p = p->next->next)//对原链表random指针的复刻。
{
if (p->random)
p->next->random = p->random->next;
}
auto dummy = new ListNode(-1); //虚拟头结点
auto cur = dummy; //尾节点
for (auto p = head; p; p = p->next) //将原链表和复刻链表拆分出来,并将原链表复原。
{
cur->next = p->next;
cur = cur->next;
p->next = p->next->next;
}
return dummy->next;
}
};
/**
* Definition for singly-linked list with a random pointer.
* class ListNode {
* int val;
* ListNode next, random;
* ListNode(int x) { this.val = x; }
* };
*/
class Solution {
public ListNode copyRandomList(ListNode head) {
if(head == null)
return null;
ListNode cur = head;
while(cur != null){
ListNode temp = new ListNode(cur.val);
temp.next = cur.next;
cur.next = temp;
cur = cur.next.next;
}
cur = head;
while(cur != null){
ListNode temp = cur.next;
if(cur.random != null){
temp.random = cur.random.next;
} else {
temp.random = new ListNode(-1);
}
cur = cur.next.next;
}
// 创建一个头节点 便于返回节点
ListNode H = new ListNode(0);
H.next = head.next;
cur = head;
while(cur != null){
ListNode temp = cur.next;
cur.next = cur.next.next;
if(temp.next != null){
temp.next = temp.next.next;
}
cur = cur.next;
}
return H.next;
}
}
9. 二叉搜索树与双向链表
原题链接
就在中序递归遍历的基础上改了一点点,用一个pre指针保存中序遍历的前一个结点。
因为是中序遍历,遍历顺序就是双线链表的建立顺序;
每一个结点访问时它的左子树肯定被访问过了,所以放心大胆的改它的left指针,不怕树断掉;
同理,pre指向的结点保存的数肯定小于当前结点,所以其左右子树肯定都访问过了,所以其right指针也可以直接改。
最后需要一直向左找到双向链表的头结点。
/**
* Definition for a binary tree node.
* struct TreeNode {
* int val;
* TreeNode *left;
* TreeNode *right;
* TreeNode(int x) : val(x), left(NULL), right(NULL) {}
* };
*/
class Solution {
public:
TreeNode* pre = NULL;
TreeNode* convert(TreeNode* root) {
dfs(root);
while(root && root->left) root = root->left;
return root;
}
void dfs(TreeNode* root){
if(!root) return;
dfs(root->left);
root->left = pre;
if(pre) pre->right = root;
pre = root;
dfs(root->right);
}
};
class Solution {
TreeNode first = null;
TreeNode last = null;
public TreeNode convert(TreeNode root) {
helper(root);
return first;
}
private void helper(TreeNode node) {
if (node == null) {
return;
}
helper(node.left);
if (last == null) {
first = node;
} else {
last.right = node;
node.left = last;
}
last = node;
helper(node.right);
}
}