学习目标:
每天2-3到简单sql(刷完即止),每天复习代码随想录上的题目3道算法(时间充足可以继续),背诵的八股的问题也在这里记录了
今日碎碎念:
1)偶尔还是贪玩游戏,但是进度有在往前,八股计划准备这些,计网,JVM,JUC,Java基础与集合,MySQL,Redis,Spring和Spring Boot,整体下来,热门的能准备到70%就开投。
2)明天是java基础和MySQL以及Redis的八股
3)哎还有科三科四没考,只能约到3月15号的,刚好一边准备面试。
4)项目还得优化一两道,简历还会再修改几次。
力扣刷题
SQL
力扣1075:1075. 项目员工 I
解答思路:
1)本题练习到了分组的思路,round函数和avg函数的使用
2)通过project_id一分组就可以求得分组后每个组里面的员工以及工作年限,此时使用avg就可以求得平均值了,不清楚的话也可以先通过sum(Employee.experience_years),来验证工作年限和是否跟预期一样
java
# 首先想到的肯定是根据Project_id来进行分组
# 然后去求得当前项目每个员工的工作年限,要实现这一想法就只能是两表连接查询了
# 最后求平均AVG,同时使用round来精确小数位数
select Project.project_id,round(avg(Employee.experience_years),2) as average_years
from Project,Employee
where Project.employee_id = Employee.employee_id
group by Project.project_id
力扣1667:1667. 修复表中的名字
解答思路:
1)本题练习到基础函数的使用,concat,upper,lower,substring(截取的字段,位置,截取长度)
java
# 本题就是练习到基础函数的使用
# 通过substring截取首字母,然后通过UPPER转化为大写,LOWER转化为小写
# 最后使用concat来连接两者
select
user_id,
concat(UPPER(substring(name,1,1)),LOWER(substring(name,2,length(name)))) as name
from Users
order by user_id
力扣1179:1179. 重新格式化部门表
解答思路:
1)这道题的解题以及代码实现呢我都是没见过的,就记录一下吧
2)这类题都是行转列
3)注意写法:case month when 'Jan' then revenue end的意思是,如果month是Jan的话就返回对应的revenue的值
java
# 把所有的revenue聚合处理,如果month的值是Jan,那么结果就是revenue,否则忽略。
select id,
sum(case month when 'Jan' then revenue end) as Jan_Revenue,
sum(case month when 'Feb' then revenue end) as Feb_Revenue,
sum(case month when 'Mar' then revenue end) as Mar_Revenue,
sum(case month when 'Apr' then revenue end) as Apr_Revenue,
sum(case month when 'May' then revenue end) as May_Revenue,
sum(case month when 'Jun' then revenue end) as Jun_Revenue,
sum(case month when 'Jul' then revenue end) as Jul_Revenue,
sum(case month when 'Aug' then revenue end) as Aug_Revenue,
sum(case month when 'Sep' then revenue end) as Sep_Revenue,
sum(case month when 'Oct' then revenue end) as Oct_Revenue,
sum(case month when 'Nov' then revenue end) as Nov_Revenue,
sum(case month when 'Dec' then revenue end) as Dec_Revenue
from Department
group by id
算法
力扣19:19. 删除链表的倒数第 N 个结点
解答思路:
1)要想一次遍历就找到末尾,首先我们得使用双指针
2)为什么要使用双指针
3)可以想象这样一个场景
4)两个人赛跑,甲会一直领先乙100米,当甲到达终点的时候,乙很显然还剩100米没到终点,即剩下倒数100米
5)这里其实也是一样的思路了,我们需要定义两个指针,两者距离n个节点
6)当快指针先到了尾部的时候,说明慢指针距离尾部差n个位置,也就找到了倒数第n个节点
7)但是我们要删除的正是倒数第n个节点,因此我们得找到该节点的前一个节点,即要让快指针先走n+1个节点
java
/**
* Definition for singly-linked list.
* public class ListNode {
* int val;
* ListNode next;
* ListNode() {}
* ListNode(int val) { this.val = val; }
* ListNode(int val, ListNode next) { this.val = val; this.next = next; }
* }
*/
class Solution {
public ListNode removeNthFromEnd(ListNode head, int n) {
//要达到n+1,我们得建立虚拟头节点
ListNode dum = new ListNode(-1);
ListNode fast = dum;
ListNode slow = dum;
dum.next = head;
//让fast先走n+1步
for(int i = 0;i<=n;i++){
fast = fast.next;
}
//然后一同前进
while(fast != null){
fast = fast.next;
slow = slow.next;
}
//改变指向即可达到删除目的
slow.next = slow.next.next;
return dum.next;
}
}
力扣160:160. 相交链表
解答思路:
双指针做法
1)我自己在做这些链表题目的时候,都会画图(脑子里也可以),画图之后就不一定会那么抽象了
2)举个例子,你认识了一个女生,在认识之前,你俩各自走各自的路,各自活自己的,如果很幸运你俩结婚了(有相交点),那么以后的日子你俩将会陪伴终生(有相交部分,即交点后的元素都是相同的)
3)那么我们就需要先找到两者的长度以及尾部,将两者尾部对齐,然后移动到同一起点之后去判断是否有交集即可
java
/**
* Definition for singly-linked list.
* public class ListNode {
* int val;
* ListNode next;
* ListNode(int x) {
* val = x;
* next = null;
* }
* }
*/
//简单来说,就是求两个链表交点节点的指针。
public class Solution {
public ListNode getIntersectionNode(ListNode headA, ListNode headB) {
ListNode curA = headA;
ListNode curB = headB;
int lenA = 0, lenB = 0;
while (curA != null) { // 求链表A的长度
lenA++;
curA = curA.next;
}
while (curB != null) { // 求链表B的长度
lenB++;
curB = curB.next;
}
//统计完之后,重置两个cur
curA = headA;
curB = headB;
//下面这段代码的目的就是判断谁更长,因为我们在让两者到尾部对齐的时候并没有去判断谁短谁长
//都是用的A来移动
// 让curA为最长链表的头,lenA为其长度
if (lenB > lenA) {
//1. swap (lenA, lenB);
int tmpLen = lenA;
lenA = lenB;
lenB = tmpLen;
//2. swap (curA, curB);
ListNode tmpNode = curA;
curA = curB;
curB = tmpNode;
}
// 求长度差
int gap = lenA - lenB;
// 让curA和curB在同一起点上(末尾位置对齐)
while (gap-- > 0) {
curA = curA.next;
}
// 遍历curA 和 curB,遇到相同则直接返回
while (curA != null) {
if (curA == curB) {
return curA;
}
curA = curA.next;
curB = curB.next;
}
return null;
}
}
评论区大牛做法
java
public ListNode getIntersectionNode(ListNode headA, ListNode headB) {
if (headA == null || headB == null) return null;
ListNode pA = headA, pB = headB;
while (pA != pB) {
pA = pA == null ? headB : pA.next;
pB = pB == null ? headA : pB.next;
}
return pA;
}
作者:房建斌学算法
链接:https://leetcode.cn/problems/intersection-of-two-linked-lists/solutions/10774/tu-jie-xiang-jiao-lian-biao-by-user7208t/
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
力扣142:142. 环形链表 II
解答思路:
1)本题在判断入口在哪的证明过程直接去看随想录好了,我这里就记录一下答案
java
/**
* Definition for singly-linked list.
* public class ListNode {
* int val;
* ListNode next;
* ListNode() {}
* ListNode(int val) { this.val = val; }
* ListNode(int val, ListNode next) { this.val = val; this.next = next; }
* }
*/
class Solution {
//不太擅长写递归,所以使用虚拟头节点 + 迭代来做
public ListNode swapPairs(ListNode head) {
ListNode dum = new ListNode(-1);
dum.next = head;
ListNode cur = dum;
ListNode tmp = null;
ListNode firstNode = null;
ListNode secondNode = null;
//要交换必须要保证有两个节点
while(cur.next != null && cur.next.next != null){
//先记录第三个节点
tmp = cur.next.next.next;
//记录第一个节点
firstNode = cur.next;
//记录第二个节点
secondNode = cur.next.next;
//交换
cur.next = secondNode;
secondNode.next = firstNode;
firstNode.next = tmp;
//指针移动
cur = firstNode;
}
return dum.next;
}
}