Dawn's Blogs

分享技术 记录成长

0%

创建数据库

  • 创建数据库
1
CREATE DATABASE mytest;
  • 创建数据库,指定字符集
1
CREATE DATABASE mytest1 CHARACTER SET 'gbk';
  • 判断数据库是否存在,若不存在则创建
1
CREATE DATABASE IF NOT EXISTS mytest2;

修改数据库

  • 修改数据库的字符集
1
ALTER  DATABASE mytest1 CHARACTER SET 'utf8';

删除数据库

  • 删除数据库
1
DROP DATABASE mytest;
  • 如果数据库存在就删除
1
DROP DATABASE IF EXISTS mytest1;

最长回文子串

最长回文子串

解题思路

  1. 中心扩展算法,从每个位置出发,向两边扩展,若遇到的是回文子串,就继续扩展;若不是回文子串就结束,到下一个位置去。扩展方法:

    • 向左扩展,向左寻找与当前位置相同的字符,直到遇到不等的字符为止
    • 向右扩展,向右扩展,向右寻找与当前位置相同的字符,直到遇到不等的字符为止
    • 左右双向扩展,同时向左右扩展,直到遇到左右字符不等为止
  2. 动态规划法,用dp[i][j]表示字符串s从第i个字符到第j个字符是否未回文子串(true表示是回文子串,false表示不是回文子串)。

    • 状态转移方程dp[i][j] = dp[i+1][j-1] ^ (s[i] == s[j])
    • 边界条件
      • 只有一个字符时,肯定是回文子串dp[i][i] = true
      • 只有两个字符时,只要两个字符相等就一定是回文子串dp[i][i+1] = (s[i] == s[i+1])
阅读全文 »

二叉树的右视图

二叉树的右视图

解题思路

利用二叉树的层序遍历,将每一层的最右侧节点加入到结果中

解题代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
/**
* Definition for a binary tree node.
* type TreeNode struct {
* Val int
* Left *TreeNode
* Right *TreeNode
* }
*/
func rightSideView(root *TreeNode) []int {
if root == nil {
// 树为空
return []int{}
}
res := []int{} // 记录结果
q := []*TreeNode{root} // 队列,根节点入队

for i := 0; len(q) > 0; i++ {
p := []*TreeNode{} // p记录下一层节点
res = append(res, q[len(q)-1].Val) // 将本层最右边的节点加入结果集
for j := 0; j < len(q); j++ {
// 将下一层节点加入队列
cur := q[j]
if cur.Left != nil {
// 左子树不为空,入队
p = append(p, cur.Left)
}
if cur.Right != nil {
// 右子树不为空,入队
p = append(p, cur.Right)
}
}
q = p // 已经遍历过本层节点,将q更新为下一层节点
}

return res
}
阅读全文 »

子查询是指,一个查询语句(内查询)嵌套在另一个查询语句(外查询)内部的查询。子查询可以按照两种方法进行分类:

  • 从内查询返回的结果的条目数
    • 单行子查询
    • 多行子查询
  • 内查询是否被执行多次
    • 相关子查询:查询工资大于本部门平均工资的员工信息
    • 不相关子查询:查询工资大于本公司平均工资的员工信息
阅读全文 »

SELECT 语句的完整结构

SQL 92

1
2
3
4
5
6
7
SELECT (DISTINCT) 字段1,字段2, ... (存在聚合函数)
FROM1, 表2, ...
WHERE 多表连接条件 AND 不包含聚合函数的过滤条件
GROUP 分组
HAVING 包含聚合函数的过滤条件
ORDER BY 字段1, 字段2 (ASC / DESC)
LIMIT index, rows

SQL 99

1
2
3
4
5
6
7
8
SELECT (DISTINCT) 字段1,字段2, ... (存在聚合函数)
FROM1 (LEFT | RIGHT) JOIN2
ON 多表连接条件
WHERE 不包含聚合函数的过滤条件
GROUP 分组
HAVING 包含聚合函数的过滤条件
ORDER BY 字段1, 字段2 (ASC / DESC)
LIMIT index, rows

SELECT 语句执行过程

  1. FROM语句,找到相应的表,多表进行笛卡尔积连接
  2. ON限制多表连接条件,进行多表连接。同时考虑左外LEFT/右外RIGHT连接,补充行
  3. WHERE过滤行
  4. GROUP BY 分组。HAVING 每组的满足条件
  5. SELECT查询字段,对列上进行过滤。若有DISTINCT,对数据去重
  6. ORDER BY对结果排序
  7. LIMIT进行分页

聚合函数介绍

聚合函数作用于一组数据,并对一组数据返回一个值

常用的聚合函数

  • 适用于数值类型
    • AVG:求平均值
    • SUM:求和
  • 适用于数值类型、字符串日期类型(这些都是可比较的)
    • MAX:最大值
    • MIN:最小值
  • COUNT:计算指定字段在查询结果中出现的个数(COUNT计入NULL值,AVG = SUM / COUNT成立)
    • 统计表中记录数,使用COUNT(*) COUNT(1)效率较高
阅读全文 »

岛屿的数量

岛屿数量

解题思路

可以将grid看作是一个有向图,每个节点最多有上下左右四条边竖直或水平相邻的 1 之间有边相连,那么岛屿的数量就是图的连通分量个数。所以可以进行图的遍历,来求得连通分量的个数:

  1. 图的深度优先遍历
  2. 图的广度优先遍历
阅读全文 »

多表查询基本实现

多表查询需要连接条件(有n个表实现多表查询,至少需要n-1个连接条件)

SQL92语法

1
2
3
4
5
6
7
8
9
10
11
# 给表起别名时必须用别名,不能用原名
SELECT emp.employee_id, dept.department_name
FROM employees emp, departments dept
WHere emp.department_id = dept.department_id;
+-------------+------------------+
| employee_id | department_name |
+-------------+------------------+
| 200 | Administration |
| 201 | Marketing |
| 202 | Marketing |
| 114 | Purchasing |

SQL99语法 JOIN ON

SQL99语法采用表1 JOIN 表2 ON 连接条件的方式实现多表连接

1
2
3
SELECT emp.employee_id, dept.department_name
FROM employees emp JOIN departments dept
ON emp.department_id = dept.department_id;

注意:

  • 多表查询需要有连接条件。若没有连接条件,可能会出现笛卡尔积错误(两个集合中的每一个成员,都与对方集合中的任意一个成员有关)
  • 多表查询时,建议每个字段前指明其所在的表。从SQL优化的角度来讲,这样避免了在各个表中找相应字段的时间。
  • 表起别名必须用别名,不能用原名
阅读全文 »

反射的基本介绍

反射就是程序在运行时,通过检查其定义的变量以及值,进而找到其对应的真实类型

reflect包

reflect包实现了运行时反射,允许程序操作任意类型的对象。典型用法是用静态类型interface{}保存一个值,通过调用TypeOf获取其动态类型信息,该函数返回一个Type类型值。调用ValueOf函数返回一个Value类型值,该值代表运行时的数据。

reflect.Type和reflect.Value

interface{}类型变量其具体类型可以使用reflect.Tpye来表示,而其具体值则使用reflect.Value来表示

1
func ValueOf(i interface{}) Value

ValueOf返回一个初始化为i接口保管的具体值的Value

1
func TypeOf(i interface{}) Type

TypeOf返回接口中保存的值的类型

reflect.Kind

reflect还有一个比较重要的类型Kind,表示具体类型

1
func (v Value) Kind() Kind

Kind返回v持有的值的分类,如果vValue零值,返回值为Invalid

  • Type代表实际类型,如包名.Student
  • Kind代表具体类型,如struct
  • 如果使基本数据类型,Type和Kind相同

NumField()和Field()

1
func (v Value) NumField() int

返回v持有的结构体类型值的字段数,如果vKind不是Structpanic

1
func (v Value) Field(i int) Value

返回结构体的第i个字段(的Value封装)。如果vKind不是Structi出界会panic

Elem()

1
func (v Value) Elem() Value

Elem返回v持有的接口保管的值的Value封装,或者v持有的指针指向的值的Value封装。如果vKind不是InterfacePtrpanic

1
2
3
4
5
6
7
8
9
10
11
12
func reflectElemTest(i interface{}) {
// 获取Value
rVal := reflect.ValueOf(i)
// 改变num的值
rVal.Elem().SetInt(20)
}

func main() {
num := 10
reflectElemTest(&num)
fmt.Println(num) // 20
}

Method()和Call()

1
func (v Value) Method(i int) Value

返回v持有值类型的第i个方法的已绑定(到v的持有值的)状态的函数形式的Value封装。如果i出界,或者v的持有值是接口类型的零值(nil),会panic

  • 方法排序是按照方法名字进行排序
1
func (v Value) Call(in []Value) []Value

Call方法使用输入的参数in调用v持有的函数。例如,如果len(in) == 3v.Call(in)代表调用v(in[0], in[1], in[2])(其中Value值表示其持有值)。如果vKind不是Funcpanic。它返回函数所有输出结果的Value封装的切片。如果v持有值是可变参数函数,Call方法会自行创建一个代表可变参数的切片,将对应可变参数的值都拷贝到里面。

经过几日的学习后,本人总结出两种可以实现线程间同步的方法:

  • sync.WaitGroup类型
  • 管道channel
    • 关闭管道
    • 带缓冲区的管道
    • 没有缓存区的管道

其中,sync.WaitGroup和带缓冲区的管道适用于多个并行线程简得同步,其他的方法只适用于两个线程的同步

阅读全文 »