LeetCode刷题-44.通配符匹配
题目链接:44.通配符匹配
¶题解:
又是一道关于正则表达式匹配问题的,和上一道10.正则表达式匹配几乎类似!
同样的做法,再来一次动态规划!
¶题目简述:
? :可以匹配任何单个字符。
*: 可以匹配任意字符串(包括空字符串)。
给一个字符串,给一个正则,检查能否匹配。
很明显,这个定义和正则的含义不尽相同,没关系,根据题意来就行了。
¶题解:
同样使用闫式DP分析法:
分为状态表示和状态计算:
如下图,由于我写过了一遍,就不再写了!
状态转移方程如下:
当p[j] != '*' f[i][j] = f[i - 1][j - 1] && (s[i] == p[j] || p[j] == '?')
当 p[j] == '*' f[i][j] = f[i][j - 1] || i && f[i - 1][j] (添加 i 防止越界)
注意点:
初始状态f[0][0] = true
j从0开始无意义,因为非空串无法匹配空串
第一个if同样需要防止越界
最终答案为f[n][m]
将字符串从0开始,可以省去边界情况的处理
时间复杂度:O(n ...
LeetCode刷题-43.字符串相乘
题目链接:43.字符串相乘
¶题解:
高精度乘以高精度!
¶题目简述:
两个字符串高精度相乘返回结果的字符串!
¶题解:
模拟小学乘法即可!
两个数相乘,最后积的位数为两数长度之和或者为长度之和减 1 !
思路:
先将字符串映射成数字,再倒序存到数组,为了方便计算!
两层循环,让第二个数的每一位去乘第一个数,存到新数组c[i + j],这样可以保证该放到同一列的都在同一列
然后将需要进位的给了下一位,即c[i + j + 1] += c[i + j] / 10
再将本位的余数留下即可,即c[i + j] %= 10
最后需要将末尾的零去掉,即反转为正常数字的前导0.(例如乘以0,或者位数为两数之和减 1)
在将其映射为字符串,倒序存储到新数组,返回!
算了,懒得画图了,太好理解了!
时间复杂度: O(n * m)
¶AC代码:
123456789101112131415161718192021class Solution {public: string multiply(string num1, string num2) { int n = num1.s ...
LeetCode刷题-42.接雨水
题目链接:42.接雨水
¶题解:
多种做法,第一次接触确实有点难,单调栈的应用,以及双指针这个神奇算法的应用!
计算这种面积,不要瞎想,大概两种,一种计算纵向,一种计算横向!
下面三种解法,推荐去看双指针和单调栈,学习算法,尽可能多的一题多解,双指针解法是最优的,但是单调栈也是一种思想,多学点没坏处!
¶题目简述:
接雨水,给定一堆柱子,问柱子之间的凹槽最多放多少水!如下图:蓝色部分就是最多的接水量。
¶题解一:三次扫描
计算纵向:即每个柱子上方可以存水的量,累加即可!
如何计算?
观察会发现,当前柱子能存的水取决于当前柱子左边最高的柱子和当前柱子右边最高的柱子,由于短板效应,所以能存的水为左右两边最高的柱子的较小值与当前柱子高度的差值。
如何计算左右最高的柱子?
简单办法:直接扫描一遍即可,使用两个数组保存该位置左右的最高柱子,left_max[i]表示i位置(包括自己)的柱子左边的最高柱子,同理right_max[i]表示i位置(包括自己)右边最高柱子。一个从左向右扫描维护该数组,一个从右向左扫描维护该数组即可。
第三次扫描,直接计算每个柱子的可存水的高度即可!即min( ...
LeetCode刷题-41.缺失的第一个正数
题目链接:41.缺失的第一个正数
¶题解:
一种排序算法的应用?
¶题目简述:
给定一组未排序数组,找出其中没有出现过的最小正整数!
要求:时间 O(n) 空间 O(1)
¶题解:
由于时间为O(n)限制,不能直接使用sort再扫描,现在给出一种排序:
小于等于0,大于 n 的数字不用管(因为我们要正数的排序,排序的最后一个数应该为n,所以大于n的不用管)
从前向后扫描,保证每个数字出现在正确位置上,即 5 应该跑到下标为 4 的位置,即nums[i]要跑到下标为nums[i] - 1的位置
扫描一遍以后,整个数组1 ~ n的数字已经正确归位,所以只需要从前向后再扫描一遍没出现过的数字即可,即nums[i] != i + 1。若全部匹配,则说明是第 n +1 个数没有出现
具体解释:
遇到1 ~ n的就进行归位,将该数放到该放的位置,使用swap进行交换,交换完成后一个数已经归位,交换过来的数若不是它该待的正确位置,继续进行交换,直到当前位置为正确数字或遇到不在1 ~ n范围内的数结束当前位置。
时间复杂度: 别看有两层循环,但是两层循环加起来最多执行n次,因为whil ...
数据库教程之字符集.安全管理.维护
¶一、字符集和校对顺序
¶1、字符集和校对顺序
在MySQL的正常数据库活动( SELECT 、 INSERT 等)中,不需要操心太多的东西。使用何种字符集和校对的决定在服务器、数据库和表级进行。
字符集为字母和符号的集合;
编码为某个字符集成员的内部表示;
校对为规定字符如何比较的指令。
¶2、使用字符集和校对顺序
¶2.1 查看支持的字符集
使用命令:SHOW CHARACTER SET;
callation为校对顺序!
这条语句显示所有可用的字符集以及每个字符集的描述和默认校对。
123456789101112131415161718192021mysql> SHOW CHARACTER SET;+----------+---------------------------------+---------------------+--------+| Charset | Description | Default collation | Maxlen |+----------+-------------------- ...
数据库教程之游标及触发器
¶一、游标
游标(cursor)是一个存储在MySQL服务器上的数据库查询,它不是一条SELECT语句,而是被该语句检索出来的结果集。
在存储了游标之后,应用程序可以根据需要滚动或浏览其中的数据。
游标主要用于交互式应用,其中用户需要滚动屏幕上的数据,并对数据进行浏览或做出更改。
注意:只能用于存储过程 不像多数DBMS,MySQL游标只能用于存储过程(和函数)。
¶1、使用游标
在声明游标后,可根据需要频繁地打开和关闭游标。在游标打开后,
可根据需要频繁地执行取操作。
首先声明(定义)游标。这个过程实际上没有检索数据,只是定义要使用的SELECT语句。
声明后,必须打开游标使用。这个过程用前面定义的SELECT语句把数据实际检索出来。
对于填有数据的游标,根据需要取出(检索)各行
结束游标使用时,必须关闭游标
¶2、创建游标
游标创建用DELCARE语句,(和前面的存储过程中声明变量的关键字一样)。
DECLARE命名游标,并定义相应的SELECT语句,根据需要带WHERE和其他子句。
DECLARE 语句用来定义和命名游标,这里为 ordernumbers 。 存 ...
数据库教程之表.视图.存储过程
¶一、创建表
¶1、简单示例如下:
12345678910111213CREATE TABLE customers( cust_id int NOT NULL AUTO_INCREMENT, cust_name char(50) NOT NULL, cust_address char(50) NULL, cust_city char(50) NULL, cust_state char(50) NULL, cust_zip char(50) NULL, cust_country char(50) NULL, cust_contact char(50) NULL, cust_email char(50) NULL, PRIMARY KEY(cust_id)) ENGINE = InnoDB;
新表的名字,在关键字create table之后给出
表列的名字和定义,用逗号分隔
使用PRIMARY KEY()指出主键
使用ENGINE = InnoDB指出使用的引擎
¶2、IF NOT EXISTS
如果你仅想在一个表不存在 ...
LeetCode刷题-40.组合总和II
题目链接:40.组合总和II
¶题解:
和上一道类似,递归解决,多了一个限制!
¶题目简述:
给定一个数组(可能有相同元素),每个数只能用一次,求出和为目标值的组合。组合不能重复。
¶题解:
上一题是没有相同元素,一数可多选。本题是有相同元素,一数只能一选。
关键点:将上一道题的 dfs(candidates, target - candidates[i], i)的i改为i + 1即可,即可以保证一数一选。
第二点 :需要进行判重,先排序,使得相同元素扎堆在一起,然后在进行同位置的选取时,进行判断跳过相同元素即可if(i > start && candidates[i] == candidates[i - 1]) continue;,这样会保证路径在同一个位置的选取不会重复,即可以保证结果不会有重复组合。
具体如何判重:
如果是同一个位置的第一次选取,是不会影响的,由于i > start,第一次进去是i == start,同一个位置的多次选取,即回溯时遇到的for循环,candidates[i] == candidates[i - 1],这个条件则 ...
LeetCode刷题-39.组合总和
题目链接:39.组合总和
¶题解:
递归同一元素可重复选取的解决,用减法减到 0 为止!
当然也可以加法加到目标值,都行!
¶题目简述:
给定一个无重复元素的序列,找到符合目标值的所有组合,不重复的组合。
¶题解:
使用深搜即可,关键点,每个数可以选不止一次。
本题可进行累加,也可以进行累减。推荐使用累减版本!
具体解决:
dfs(vector<int>& candidates, int target, int start)
start用来指向从该数组的哪一个数进行循环。
递归出口:
target < 0,即已经将目标值减没了,可以return了。
target == 0,恰好等于0,则说明找到了一种组合,将当前有效路径path加入答案res
从start开始循环,path添加当前选取值,进行下一轮dfs(candidates, target - candidates[i], i),start仍然从i开始即可,选同一个数的最多次,超过即target < 0,直接返回
同一个数的最多次选择完毕将会进入下一个数的选取。
for循环内dfs的结 ...
LeetCode刷题-38.外观数列
题目链接:38.外观数列
¶题解:
嗯,做这种题得有宏观思想,我就是被细小地方搞混乱了!
也是双指针的思想。
¶题目简述:
给定一个序列1,接下来每一项都是前一项的描述,详细请看官网描述!
¶题解:
说白了,就是从前一项找到相同的字符的起始位置即可。。
例如:12233344只要能分成1、22、333、44四段即可!
具体思路:
借助双指针思想,一个指向该段起点j,一个指向该段最后一个位置的下一个位置k即可。该段的长度就是k - j,该段的字符就是s[j]。
即最终为t += to_string(k - j) + s[j]
注意 :使用两个变量来回切换,s指向上一个,t指向当前。以及j = k,来进行动态跳转到下一段位置起点!
关于 to_string():
C++11支持的转换字符串函数,在这里如果不使用这个函数,也可以通过'0' + k - j,但是这样有个缺点,不能超过ASCII码的范围!
¶AC代码:
1234567891011121314151617class Solution {public: string countAndSay(int n) { ...
LeetCode刷题-37.解数独
题目链接:37.解数独
¶题解:
好了,来开始解数独了!
¶题目简述:
同上一题,都是数独,此题用来解数独。
¶题解:
这道题的第一个关键在于填数字的时候如何处理行列即九宫格是否有该数!
同上一题的判断有效性,使用三个数组row[9][9], col[9][9], cell[3][3][9]来分别指向九行,九列,九个九宫格,的九个数来进行标记。
对于九宫格的处理:
可以对行列取除i / 3, j / 3,会发现只要是在九宫格他们得到的结果一定是每个九宫格左上角的坐标位置,这样就可以进行轻松的标记!
递归过程:
递归出口,由于从左到右从上到下进行爆搜,所以:
若y == 9,则x ++, y = 0,即到了行末,进行换行
若x == 9,则return true ,即已经搜完了最后一行最后一个了,直接返回
若当前搜到的为.,则直接跳过,return dfs(board, x, y + 1)
否则,进行循环搜索,若行列九宫格都没有重复,则填充当前值,并将行列九宫格都标记为true
继续向后搜索,若可以搜到底,直接返回true,说明找到了一种情况。
否则,进行回溯,取消标记, ...
LeetCode刷题-36.有效的数独
题目链接:36.有效的数独
¶题解:
数独游戏的到来,这道题判断是否有解,下一道题咱们来填数独!
¶题目简述:
给定一个9 X 9 的数独,判断当前状态是否有解!
¶题解:
判断是否有解,即判断行和列以及九个小九宫格是否会出现一个数多用的情况即可!
判断行:直接遍历即可,每行进行一下数组清零
判断列:将i, j调换一下即可!每列进行一下数组清零
判断九宫格:可以使用i, j指向每个九宫格的第一个位置代表不同的九宫格,即i, j += 3
然后再在个九宫格中使用两层循环遍历九个格子即可,每个九宫格进行数组清零,指向的位置即为i + x, j + y
使用过直接返回false,全部遍历完都没问题,则返回true
注意:要将数独中的字符转变为数字进行!转换为了1 - 9
¶AC代码:
1234567891011121314151617181920212223242526272829303132333435363738394041class Solution {public: bool isValidSudoku(vector<vector<char> ...