leetcode:今天刷leetcode 链表问题非常之经典啊。
leetcode160:香蕉链表
返回相交结点:很自然想到两个指针,但是两个指针一起走不能同时到达香蕉点,因此需要长的那个先走,这里B应该先走一下,如何计算差值?list B - list A即可。
leetcode260:反转链表
典!啥也不说了,维护三个指针,使得断开的两个链表之间“藕断丝连”;贴个代码好了。
ListNode* reverseList(ListNode* head) {
//虚拟节点
if( head == nullptr || head->next == nullptr) return head;
ListNode * left = nullptr;
ListNode * mid = head;
ListNode * right = head->next;
while(mid!=nullptr)
{
//反转
mid->next = left;
left = mid;
mid = right;
if(right->next!=nullptr) right = right->next;
if(mid->next == nullptr) break;
}
mid->next = left;
return mid;
}
最后一个还没连上,手动连一下,不一定需要放在循环里面处理。
leetcode234:回文链表
思路1:修改为双向链表
思路2: 重新new一个连边,然后遍历一遍原来的链表,不断在new链表头上加入新节点,再进行比较。
leetcode141 and 142:
快慢指针问题:啥也不说了贴个代码
ListNode *detectCycle(ListNode *head) {
if(head == NULL) return NULL;
if(head->next == NULL) return NULL;
if(head->next->next == NULL) return NULL;
ListNode* slow = head;
ListNode* fast = head;
while(fast != NULL && fast->next!=NULL && fast->next->next!=NULL)
{
fast = fast->next->next;
slow = slow->next;
if(fast == slow)
{
slow = head;
while(fast!=slow)
{
fast = fast->next ;
slow = slow->next ;
}
return fast;
}
}
return NULL;
}
证明的话思路就是第一次相遇之后,如果希望下一次在环口相遇,则必须有一个人退到环剩余距离去,然后根据第一次相遇的等式可以知道R = (1-x)C,R是直线,C是环,x是当前走了环的x比例。
1. SQL查询语句的执行过程
如上图(来源极客时间),基本分为客户端,Server层,引擎等三个大块。客户端分离给客户使用,连接器负责和客户端进行连接。
连接器:
mysql -h$ip -P$port -u$user -p
当用户连接请求被通过后,连接器会从权限表读出该用户的权限,之后的逻辑判断都依赖与此时读到的权限。也就意味着本次连接,权限无法被改变,即使管理员修改了你的权限。
SHOW PROCESSLIST可以查询目前的连接用户以及其的状态。连接器有超时断连的机制。
长连接 VS 短连接:
短连接每次都需要三次握手,四次挥手,耗时。但是长连接需要消耗较大的内存,长时间积累下来的话会导致内存过大,MySQL可能会被系统杀死,导致异常重启。
查询缓存:
这里没什么好说的,但是对于数据库这样一个频繁更新的场景来说,根据经验,维护一个正确的缓存需要消耗的资源更多了,MySQL 8.0之后就删除缓存了。
分析器:
词法分析+语法分析
优化器:
优化器如何执行这个语句
执行器:
查询权限,是否使用索引,调用存储引擎的接口去执行。
2. MySQL的日志系统
两个日志模块:
1)redo log(存储层的日志):InnoDB独有 的 redo log 是固定大小的,比如可以配置为一组 4 个文件,每个文件的大小是 1GB,那么这块“粉板”总共就可以记录 4GB 的操作。从头开始写,写到末尾就又回到开头循环写,如下面这个图所示。循环利用,写满了之后就往磁盘里面写。
2)binlog (Sever层日志): 刚开始MySQL使用的是MyISAM引擎,没有redo log。
redo log 是物理日志,记录的是“在某个数据页上做了什么修改”,binlog 是逻辑日志,记录的是这个语句的原始逻辑,比如“给 ID=2 这一行的 c 字段加 1 。
binlog 是可以追加写入的。“追加写”是指 binlog 文件写到一定大小后会切换到下一个,并不会覆盖以前的日志。
如何恢复数据库到某一秒?
当需要恢复到指定的某一秒时,比如某天下午两点发现中午十二点有一次误删表,需要找回数据,那你可以这么做:
- 首先,找到最近的一次全量备份,如果你运气好,可能就是昨天晚上的一个备份,从这个备份恢复到临时库;
- 然后,从备份的时间点开始,将备份的 binlog 依次取出来,重放到中午误删表之前的那个时刻。