0


刷题笔记之八(字符串通配符+参数解析+计算日期到天数)

1. dateadd(datepart,number,date)函数是在日期中添加或减去指定的时间间隔

在MySQL中没有getdate()这样的函数,但是有dateadd()函数,但里面却是两个参数的

而在SQL Server中是有getdate() 和 dateadd()函数

dateadd(datepart,number,date)函数是在日期中添加或减去指定的时间间隔

datapart参数的取值范围{yy/yyyy , mm/m , dd/d}

number 是希望添加的间隔数 (往前是负数,往后是正数)

date 参数是合法的日期格式

getdate()函数从SQL Server 返回当前的时间和日期

而在MySQL中获取当前日期和时间的函数为now()

MySQL中的dateadd(date , initerval expr type)函数

date 参数是合法的日期表达式

expr 参数是希望添加的时间间隔


2. DML数据库操作语言负责数据的增删查改


3. 修改表结构的关键字都是alter table 表名,再加修改的语句

修改表结构的关键字都是alter table 表名,再跟具体修改的语句

(1)添加表字段

alter table table_name add 字段名称 字段类型

(2)删除表字段

alter table table_name drop 字段名称

(3)修改表字段

alter table table_name change 旧字段名称 新字段名称 字段类型

alter table table_name modify 字段名称 字段类型


4. between and条件查询范围前闭后闭

题中需要的是[1,10)

(1)使用between and 表示的查找范围是 【前闭后闭的】,所以A对

(2)interval

a)当做函数时,它被当做比较函数interval(),

比如interval(4,0,1,2,3,4,5,6)在这个函数中第一个数字4作为被比较数,后面的0 1 2 3 4 5 6当做比较数,将4和后面的数字进行比较,返回 <= 4的个数,所以这里返回5

(要将4后面的数字从小到大排序,interval才能正常使用,不然结果可能会错误)

b)当做关键字时,表示时间间隔,常用在data_add()、data_sub()函数中,

常用于时间的加减法,

比如查询当前时间之前2个小时的日期:select now()-interval 2 hours;

now()用来表示当前日期


5. 使用索引 in 范围查询,like是用作模糊查询的

条件查询根据范围这里使用in比较合适

like是依赖一些通配符来表示要匹配的值是啥样的

% 代替任意个任意字符 _代替一个任意字符


6. group by子句进行分组,having进行行条件筛选

group by 子句进行分组后,如果要对分组结果进行条件筛选时,不可以使用where语句,而要使用having ,进行 行筛选


7. 字符串通配符

题目链接:字符串通配符_牛客题霸_牛客网 (nowcoder.com)

题目要求:

题目分析:

一般动态规划的问题都可以通过穷举的方式得到答案,既然可以穷举,我们就可以将这个问题抽象成树形结构问题,然后通过回溯来解决

这块的思路是在力扣中看到【狗大王】写的,极为清晰,感兴趣的也可以点这个去了解一下

一个棋盘看懂动态规划(DP)思路;附Python代码 - 通配符匹配 - 力扣(LeetCode)

先看这样一般表

横轴为string s,纵轴为pattern p

这个表第(m,n)个格子所要表示的是,【p从0位置到m位置】这样一段

是否能与【s从0位置到n位置】这一整段匹配

此时在(start,start)位置放了一个T,这就是开始行走的位置

只有在T时才可以继续往下走,那T往这个表格哪里走?

这个题是一个字符串匹配题,那么字符串匹配肯定是从前往后匹配啊,对应到这个表格中,那就是往右下角走(也可以是往右走、往下走)

往右下角走,比如从刚才的初始位置出发,往右下角走一格,来到(a,a)的位置,发现这两个字母匹配,那就在这里记录一个“T”

就是这么走,如果p和s里只有字母,没有“ * ” 和 “ ? ” 这两个东西,那就是每次只要从原来T的某个格子往右下角走一格,如果新引入的两个字母正好匹配,那就可以在新的格子里记录一格T

注意:只能从T的格子走,如果某个格子没有东西(F),是不可以从那里走的

下面来看 “ * ” 和 “ ?”

可以将这个表格和象棋棋盘进行对比,普通字母如a、b就像是小兵角色,遇到他们只能右下走一格,走完这一步后判断新入的两个字母是否匹配才能记录T;而 “ * ” 和 “ ?”就像是有特殊技能的角色

“ * ” :如果这一行是 “ * ” ,可以从上一行的任意T出发,向下、往右来走(T)

“ * ”可以从原来T向正下方走的原因:*可以匹配空串

“ * ”可以往右走的原因:*可以匹配任意长度字符串

然后接着走,遇到一个b,这个是一个普通字母,所以只能从上一行某个T往右下角走到达,而且字母匹配才能记录T,于是可以这样走

下面就是 “ ?”

“ ?”:如果这一行是“ ?”,从上一行某个T也只能往右下角走,但不必匹配字母就能记录T

这样就到了最后一格,普通字母小兵,匹配

要判断是否匹配成功,此时只要看一个格子,如果最右下角的格子是T,那就是匹配成功了

力扣中这道题:44. 通配符匹配 - 力扣(LeetCode)

代码

class Solution {
    public boolean isMatch(String s, String p) {
  int m = s.length();
        int n = p.length();
        boolean[][] matchMap = new boolean[m+1][n+1];
        matchMap[0][0] = true;
        for (int i = 0;i<=m;i++){
            for (int j = 1;j<=n;j++){
                if (p.charAt(j-1)!='*'){
                    if (i>=1&&(p.charAt(j-1)==s.charAt(i-1)||p.charAt(j-1)=='?'))
                        matchMap[i][j] = matchMap[i-1][j-1];
                }else 
                    matchMap[i][j] = i==0?matchMap[i][j-1]:matchMap[i-1][j]||matchMap[i][j-1];
            }
        }
        return matchMap[m][n];
    }
}

上代码(牛客)


import java.util.Locale;
import java.util.Scanner;

public class Main {
    public static void main(String[] args) {
        Scanner scan = new Scanner(System.in);
        String s = scan.nextLine();
        String t = scan.nextLine();
        System.out.println(wildcard(s,t));
    }

    private static boolean wildcard(String t, String s) {
      char[] ct = t.toCharArray();
      char[] cs = s.toCharArray();
      int lt = ct.length;;
      int ls = cs.length;
      boolean[][] dp = new boolean[ls+1][lt+1];
      dp[0][0] = true;
        for (int i = 0; i <= ls; i++) {
            for (int j = 1; j <= lt; j++) {
                if(ct[j-1] == '*') {
                    if(i == 0) {
                        dp[i][j] = dp[i][j-1];
                    }else {
                        if(cs[i-1] == '.' || (cs[i-1] >= 'A' && cs[i-1] <= 'Z') ||
                                (cs[i-1] >= 'a' && cs[i-1] <= 'z') ||
                                (cs[i-1] >= '0' && cs[i-1] <= '9')) {
                            dp[i][j] = dp[i-1][j] || dp[i][j-1];
                        }
                    }
                } else {
                    if(i > 0 && defs(ct[j-1],cs[i-1])) {
                        dp[i][j] = dp[i-1][j-1];
                    }
                }
            }
        }
        return dp[ls][lt];
    }

    private static boolean defs(char t, char s) {
        if(t == '?') return true;
        if(t >= 'a' && t <= 'z') {
            t = (char)(t-'a'+'A');
        }
        if(s >= 'a' && s <= 'z') {
            s = (char)(s-'a'+'A');
        }
        return s == t;
    }
}

8. 参数解析

题目链接:参数解析_牛客题霸_牛客网 (nowcoder.com)

题目要求:

题目分析:

参数打印,空格换行,双引号中的除外

可以用一个标识位来识别是不是在双引号中,比如定义一个flag =1.遇到双引号就flag^1

也就是此时flag为0,意味着已经进入双引号中,不再根据空格来换行打印了,直到遇到后一个双引号再异或一次,以为着此时已经出了双引号了,可以继续执行空格换行打印了

上代码


import java.util.Scanner;

public class Main {
    public static void main(String[] args) {
        Scanner scan = new Scanner(System.in);
        String str = scan.nextLine();
        int count = 0;
        for (int i = 0; i < str.length(); i++) {
            //遇到双引号时,就一直遍历,直到找到第二个双引号
            if(str.charAt(i) == '"') {
                do {
                    i++;
                }while (str.charAt(i) != '"');
            }
            //双引号以外的空格 count++;
            if(str.charAt(i) == ' ') {
                count++;
            }
        }
        //count是空格的个数,参数个数为count+1
        System.out.println(count+1);
        int flag = 1;
        for (int i = 0; i < str.length(); i++) {
            //遇到双引号异或,来标识此时进入了双引号中
            if(str.charAt(i) == '\"') {
                flag ^= 1;
            }
            
            if(str.charAt(i) != ' ' && str.charAt(i) != '\"') {
                System.out.print(str.charAt(i));
            }
            //flag=0时,一直在遍历双引号中的参数
            if(str.charAt(i) == ' ' && flag == 0) {
                System.out.print(str.charAt(i));
            }
            //遇到双引号以外的空格就需要换行
            if(str.charAt(i) == ' ' && flag == 1) {
                System.out.println();
            }
        }
    }
}

9. 关系数据库六种范式

** 先来了解一下什么叫范式**

范式是符合某一级别关系模式的集合

关系数据库的关系必须满足一定的要求,满足不同程度要求的不同范式,目前关系数据库有六种范式

第一范式(1NF)、第二范式(2NF)、第三范式(3NF)、Boyce-Codd范式(BCNF)、第四范式(4NF)和第五范式(5NF)

满足最低要求的范式是第一范式(1NF),在第一范式的基础上进一步满足更多的称为第二范式(2NF),其余范式依次类推。一般来说,数据库只需满足第三范式(3NF)就可以了

第一范式(1NF):列不可再分

第一范式是最基本的范式,如果数据库中的所有字段值都是不可分解的原子值,就说明该数据库表满足了第一范式

第二范式(2NF):属性完全依赖于主键

第二范式是在第一范式的基础上建立起来的,也就是满足第二范式必须先满足第一范式。

第二范式要求数据库表中的每个实例或行必须可以被唯一的区分

每一行的数据只能与其中一列相关,即一行数据只做一件事。只要数据列中出现数据重复,就要把表拆分开

第三范式(3NF)属性不依赖于其他非主属性 属性直接依赖于主键

数据不能存在传递关系,即每个属性都跟主键有直接关系而不是间接关系

比如Student表(学号,姓名,年龄,性别,所在院校,院校地址,院校电话)

学号--》所在院校--》(院校地址,院校电话)

拆开(学号,姓名,年龄,性别,所在院校)-- (所在院校,院校地址,院校电话)

BCFN范式:所有属性都不传递依赖于关系的任何后选键

题目中关系模式满足第二范式,但在学生表S中,学生所在系(Sd)依赖学号(S#),而所在系的系主任(Dc)又依赖于学生所在系(Sd),存在传递依赖,不满足第三范式。


10. 数据库系统特点:高共享、低冗余、独立性高、具有完整性等

数据冗余度高就表示数据重复性高,而在设计数据库时对于冗余度是要求比较小的,具体做法是可以用主外键来进行关联到几张表中,从而减少数据冗余度

数据库系统特点:高共享、低冗余、独立性高、具有完整性等


11. 实体之间多对多联系在关系模型中的实现方式是 建立新的关系

实体-联系图(ER图),是一种以直观的图示化方式描述实体(集)及其之间联系的语义模型。

ER图中有四个基本成分

(1)矩形框,表示实体类型(研究问题的对象),矩形框中写明实体名

(2)菱形框,表示联系类型,菱形框内写明联系名

(3)椭圆形框,表示实体类型和联系类型的属性,椭圆内写明属性名

(4)直线,联系类型与其设计的实体类型之间以直线连接,表示它们之间的联系(1:1或1:N或M:N)

比如每个专业设置有多门课程,某些课程可被多个专业设置。专业实体集与课程实体集之间的联系在ER图中表示为多对多联系

但在关系模型中,要通过中间表来表达他们的多对多关系,所以选A


12.sum只能用于数值类型的列,Avg/Max/Min/Count都不是求和函数

B avg不属于求和函数,并且avg不能使用日期型的列

C Max和Min不属于求和函数,并且只能用于数值型的列

D Count属于不求和函数,可以用于字符型的列(count中可以使用任意类型的字段,常量也可)


13. 关系操作:自然连接、交、并、除

先来看一下这四个概念

自然连接:如果关系R与S具有相同的属性组B,且该属性组的值相等时的连接称为自然连接,结果关系的属性集合为R的属性并上S减去属性B的属性集合,自然连接也可看作是在广义笛卡尔积R*S中选出同名属性上符合相等条件元组,再进行投影,去掉重复的同名属性,组成新的关系

交:关系R与关系S的交运算结果由既属于R又属于S的元组(即R与S中相同的元组)组成一个新关系,如果两个关系没有相同的元组,那么它们的交为空

除:设关系R除以关系S的结果为关系T,则T包含所有在R但不再S中属性及其值,且T的元组与S的元组的所有组合都在R中

并:关系R与关系S的交运算结果既属于R或属于S的元组(即R和S的所有元组合并),删去重复元组,组成一个新关系,其结果仍为n元关系

本道题的过程是这样的

(1)求S中重复字段: A c B 3

(2)R中有,但S没有的字段 C:{2,1}

(3)R中,C = 2 :{a,1} C = 1:{ {b,2} , {c,3} }

对比后发现(1)中的S重复字段在 (3)的C=1中,所以这个是除


14. 关系数据库所采用的数据存放形式是 二维表


15. 员工编号有重复:不同部门,有相同的员工编号

根据业务来设计表:

(1)员工编号:可以标识数据(员工编号唯一,主键就是员工编号)

(2)员工编号有重复:不同部门,有相同的员工编号:主键就是员工编号+部门编号


16. 计算日期到天数转换

题目链接:计算日期到天数转换_牛客题霸_牛客网 (nowcoder.com)

题目要求:

题目分析:

这里需要分析的是,输入的年份是不是闰年,因为在闰年中二月是29天(正常2月是28天)

然后就是根据对应月份来计算天数,注意在计算月份中对应天数累加求和时,当月的不要计算,当月的要单独加输入的天数

上代码


import java.util.Scanner;

public class Main {
    public static void main(String[] args) {
        Scanner scan = new Scanner(System.in);
        int n = scan.nextInt();
        int y = scan.nextInt();
        int r = scan.nextInt();

        int[] array1 = new int[]{31,28,31,30,31,30,31,31,30,31,30,31};
        int[] array2 = new int[]{31,29,31,30,31,30,31,31,30,31,30,31};//润年
        int sum = 0;
        //1.先判断闰年
        if((n%4==0 && n%100 != 0) || (n%400 == 0)) {
            //为闰年,2月29天
            for (int i = 0; i < y-1; i++) {
                sum += array2[i];
            }
            System.out.println(sum+r);
        }else {
            for (int i = 0; i < y-1; i++) {
                sum += array1[i];
            }
            System.out.println(sum+r);
        }
    }
}


本文转载自: https://blog.csdn.net/m0_58761900/article/details/127567760
版权归原作者 快到锅里来呀 所有, 如有侵权,请联系我们删除。

“刷题笔记之八(字符串通配符+参数解析+计算日期到天数)”的评论:

还没有评论