[高频] 一.Interview Style

本文介绍了解码路径数量的计算方法与字符串同构性的判断逻辑,通过具体实例展示了如何利用动态规划解决解码问题,并提出了判断两字符串是否可以通过字符替换相互转化的有效算法。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

512.Decode Ways:点击打开链接

思路:总是从f[i]看前i-1位数字能够解析的结果

          有两种方式:前i-1位到前i位,只要第i-1位不是数字0,前i位的结果数就是前i-1位的结果数

                            前i-2位到前i位,只要第i-2位和第i-1位两位上的数字介于10和26之间,就会又增加一种结果数

注意:1. 新建数组的时候数组长度要多一位,s.length()+1

         2. f[0]和f[1]的初始化问题,使得如果第一位为0的字符串,返回的结果数是0

例如:01:f[0]=1, f[1]=0 -> 结果f[2]=f[1]=0

public class Solution {
    /**
     * @param s a string,  encoded message
     * @return an integer, the number of ways decoding
     */
    public int numDecodings(String s) {
        if(s==null || s.length()==0){
            return 0;
        }
        
        int[] f=new int[s.length()+1];
        f[0]=1;
        f[1]=s.charAt(0)!='0'?1:0;
        
        for(int i=2;i<=s.length();i++){
            if(s.charAt(i-1)!='0'){
                f[i]=f[i-1];
            }
            
            int twoDigits=(s.charAt(i-2)-'0')*10+s.charAt(i-1)-'0';
            if(twoDigits>=10 && twoDigits<=26){
                f[i]+=f[i-2];
            }
        }
        return f[s.length()];
    }   
}

638.Strings Homomorphism:点击打开链接

思路:两次映射,s->t一次,t->s一次

注意:不能只做一次映射,如果"app"->"dog"是可以的,但是"dog"->"app"就犯了两个字母映射到同一个字母的错误

public class Solution {
    /**
     * @param s a string
     * @param t a string
     * @return true if the characters in s can be replaced to get t or false
     */
    public boolean isIsomorphic(String s, String t) {
        if(s==null || t==null){
            return true;
        }
        Map<Character,Character> map=new HashMap<>();
        for(int i=0;i<s.length();i++){
            if(!map.containsKey(s.charAt(i))){
                map.put(s.charAt(i),t.charAt(i));
            }else{
                if(map.get(s.charAt(i))!=t.charAt(i)){
                    return false;
                }
            }
        }
        Map<Character,Character> mapSecond=new HashMap<>();
        for(int i=0;i<t.length();i++){
            if(!mapSecond.containsKey(t.charAt(i))){
                mapSecond.put(t.charAt(i),s.charAt(i));
            }else{
                if(mapSecond.get(t.charAt(i))!=s.charAt(i)){
                    return false;
                }
            }
        }
        return true;
    }
}
public class Solution {
    /**
     * @param s a string
     * @param t a string
     * @return true if the characters in s can be replaced to get t or false
     */
    public boolean isIsomorphic(String s, String t) {            //写法二:同样的思路
        if(s==null || t==null){ 
            return true;
        }
        HashMap<Character,Character> map = new HashMap<>();  
        HashSet<Character> repeat = new HashSet<>();  
        for(int i = 0;i<s.length();i++){                         //例如"dog"->"app"
            if(!map.containsKey(s.charAt(i))){                   //遍历到第三个字母,map不包含字母g,但是repeat已经有p
                if(repeat.contains(t.charAt(i))){                //repeat的p是遍历第二个字母的时候放进去的
                    return false;                                     
                }  
                map.put(s.charAt(i) , t.charAt(i));              //在双方都没有的情况下,map和repeat同步加入
                repeat.add(t.charAt(i));  
            }else{  
                if(map.get(s.charAt(i)) != t.charAt(i)){  
                    return false;  
                }  
            }  
        }  
        return true; 
    }
}

626.Rectangle Overlap:点击打开链接

思路:考虑不重合的情况,有四种相对位置


/**
 * Definition for a point.
 * class Point {
 *     public int x, y;
 *     public Point() { x = 0; y = 0; }
 *     public Point(int a, int b) { x = a; y = b; }
 * }
 */

public class Solution {
    /**
     * @param l1 top-left coordinate of first rectangle
     * @param r1 bottom-right coordinate of first rectangle
     * @param l2 top-left coordinate of second rectangle
     * @param r2 bottom-right coordinate of second rectangle
     * @return true if they are overlap or false
     */
    public boolean doOverlap(Point l1, Point r1, Point l2, Point r2) {
        if(l1.x>r2.x || r1.x<l2.x){
            return false;
        }
        if(l1.y<r2.y || r1.y >l2.y){
            return false;
        }
        
        return true;
    }
}
637.Check Word Abbreviation: 点击打开链接

思路:两个指针,分别指向两个字符串的起始位置,往后遍历,出现的情况只有数字和字母,做相应处理,直到最后

public class Solution {
    /**
     * @param word a non-empty string
     * @param abbr an abbreviation
     * @return true if string matches with the given abbr or false
     */
    public boolean validWordAbbreviation(String word, String abbr) {
        if(word==null || abbr==null){
            return false;
        }
        
        int i=0;int j=0;
        char[] w=word.toCharArray();                                   //方便后面用a[j]的形式,不用charAt麻烦
        char[] a=abbr.toCharArray();
        
        while(i<word.length() && j<abbr.length()){                     //出现的只有数字和字母两种情况
            if(a[j]>='0' && a[j]<='9'){                                //如果是数字,不能有前导零
                if(a[j]=='0'){                               
                    return false;
                }
                int val=0;
                while(j<abbr.length() && a[j]>='0' && a[j]<='9'){      //非前导零的情况拿出连着的数字的大小
                    val=val*10+a[j++]-'0';
                }
                i+=val;                                                //同时指向字符串word的指针移动相应的位数
            }else{                                                     //如果是字母,要看两边相对应的是否相同
                if(w[i++]!=a[j++]){
                    return false;
                }
            }
        }
        
        return i==word.length() && j==abbr.length();                   //直到判断到头,因为i++和j++正好是最后一个字符
    }                                                                  //所有i和j多一个,要到字符串的长度
}

639. Words Abbreviation:点击打开链接

思路:每一个单词装在HashMap里并计数,有重复就增加此单词的prefix[i]继续求,直到所有的都为unique

注意:最后HashMap里装的是分析过的所有情况的个数,而result数组里的才是结果

例如:"apple", “apble”

          最后map里{apple=1,a3e=2,apble=1,ap2e=2}

          最后result数组里{apple,apble}


public class Solution {
    /**
     * @param dict an array of n distinct non-empty strings
     * @return an array of minimal possible abbreviations for every word
     */
    public String[] wordsAbbreviation(String[] dict) {
        if(dict==null || dict.length==0){
            return new String[0];
        }
        
        int len = dict.length;
        String[] result = new String[len];
        int[] prefix = new int[len];
        Map<String, Integer> map = new HashMap<>();
        boolean unique = true;
        
        for(int i = 0; i < dict.length;i++){
            prefix[i] = 1;
            result[i] = getAbbre(dict[i], prefix[i]);
            if(!map.containsKey(result[i])){
                map.put(result[i], 1);
            }else{
                map.put(result[i], map.get(result[i]) + 1);
                unique = false;
            }
        }
        
        while(unique==false){
            unique=true;
            for(int i = 0; i < len; i ++){
                if(map.get(result[i]) > 1){
                    prefix[i]++;                                             //个数大于1里面的每一个的substring都要多一位
                    result[i] = getAbbre(dict[i], prefix[i]);
                    if(!map.containsKey(result[i])){
                        map.put(result[i], 1);
                    }else{
                         map.put(result[i], map.get(result[i]) + 1);
                         unique=false;
                    }
                }
            }
            if(unique==true){                                               //直到每一个unique=true                    
                break;
            }
        }
        return result;
    }
    
    private String getAbbre(String s,int prefix){
        if(s.length()-prefix<=2){
            return s;
        }
        return s.substring(0,prefix)+(s.length()-prefix-1)+s.charAt(s.length()-1);  //substring方法参数(起始位置,长度)
    }
}







、数据操作 1.增加数据 1)增加行数据——增加全部值 insert into 表名 values(…); 注意: a)数据值需要和表的字段完全对应(数据个数和数据类型) b)主键列是自动增长,插入时需要占位,通常使用0或者default或者null来占位 举例: insert into students values(0,'张三',28,1.78); 2)增加行数据——增加部分值 insert into 表名(字段1,…) values(值1,…); 举例: insert into students values(0,'张三',28,1.78); insert into students(name,height) values('李四',1.68); 3)增加多行数据 a)方法:多句执行单行插入语句,以分号隔开 举例: insert into students values(0,'王五',23,1.67); insert into students(name,height) values ('赵六',1.82); b)方法二:在插入单行数据的语句上,value后边的数据进行多组化处理 insert into 表名 vaues(…),(…); insert into 表名(列1,…)values(值1,…),(值1,…)…; 举例: insert into students values(0,'张',21,1.81),(1,'张二',30,1.65); insert into students(name,height) values('李三',1.54),(李四'',1.87); 2.修改数据 1)修改数据 update 表名 set 列1=值1,列2=值2… where 条件; 注意:where如果省略,代表修改整列数据,不建议省略where 举例:update students set age=48 where id=9; 3.删除数据 1)删除数据 delete from 表名 where 条件; 注意:where如果省略,代表删除全部数据,不建议省略where 举例:delete from students where id=6; 2)逻辑删除 对于重要的数据,不能轻易执行delete删除语句,因为旦删除,数据无法回复,这时会用到逻辑删除。表中增加字段isdelete,0代表未删除,1代表删除,默认值0,当需要删除某条数据时,设置该条数据的isdelete字段为1 举例: update students set isdelete=1 where id=4; select *from students where isdelete=0; 3)其他删除方法 delete from 表名 ——删除所有数据,但是不重置主键字段的计数 truncate table 表名 ——删除所有数据,并重置主键字段的计数 drop table 表名 ——删掉表(字段和数据均不再存在) 举例: delete from students; truncate table students; drop table students; 4.查询语句 1)基本查询 a)查询表内所有数据 select *from 表名; 举例:select *from students; b)查询表内部分字段 select 字段名1,字段名2 from 表名; 举例:select name,age from students; c)字段起别名查询 select 字段名 as '别名' from 表名; (引号可以省略,as也可以省略) select name as '姓名' from students; 起别名的作用:1)美化数据结果的显示效果 2)可以起到隐藏真正字段名的作用 d)去重查询 select distinct(字段名) from 表名; 举例:select distinct(company) from goods; 2)条件查询 a)逻辑运算符 select *from goods where price >30 and company != ''PDD; b)模糊查询 like % 举例: select *from goods where remark like '%次性%'; ——关键词在中间 select *from goods where remark like '%次性'; ——关键词在末尾 selects *from goods where remark like '次性%'; ——关键词在开头 c)范围查询 查询价格范围在30-100的商品信息 举例:select *from goods where price between 30 and 100; d)判断空查询 i)查询描述为空的所有商品 select *from goods where remark is null; ii)查询有描述信息的所有商品 select *from goods where remark is not null; 3)其他复杂查询 a)排序 查询说明:查询所有商品信息,按照价格从大到小排序,价格相同时,按照数量由少到多排序 select *from 表名 order by 列1 asc|desc ,列2 asc|desc,… 说明:order by ——排序;asc ——升序 ;desc ——降序 select *from goods order by price desc,count asc; 默认排序为升序,上面的asc可以省略,修改为:select *from goods order by price desc,count; b)聚合函数 i)统计记录总数 select count(*) from goods; 扩展:可以增加筛选条件,如:select count(*) from goods where name = '矿泉水'; ii)其他 select max(price) from goods; ——最高商品价格 select min(price) from goods; ——最低商品价格 select avg(price) from goods; ——商品平均价格 select sum(amount) from goods where remark like '%次性%'; ——次性商品的总金额 c)分组 i)分组查询 select 字段1,字段2,聚合… from 表名 group by 字段1,字段2… select sum(amount) from goods group by company; ——按照公司名称分组统计各个公司的金额总数 还可以分组统计数量:select count(*) from goods group by company; ii)分组后加条件过滤 select 字段1,字段2,聚合… from 表名 where 条件 group by 字段 having 条件; 举例:显示每个地区的总人口数和总面积,仅显示那些面积超过1000000的地区 select region,sum(population),sum(area) from bbc group by region having sum(area)>1000000; where 和having的区别 where是对from后面指定的表进行数据筛选,属于对原始数据的筛选 having是对group by 的结果进行筛选 having后面的条件中可以用聚合函数,where后面不可以 4)分页查询 select *from 表名 limit start,count; 举例: select *from goods limit 0,5; ——获取前5条数据 select *from goods limit 5; ——默认从条取值,0可以省略 扩展: select *from goods order by price desc limit 1; ——查询商品价格最贵的条数据信息 select *from goods order by price desc limit 3; ——查询商品价格最贵的前三条数据信息 5.连接查询 1)内连接 select *from 表1 inner join 表2 on 表1.列=表2.列 内连接查询,按照图表表示如下:取的值是A和B的交集,也就是A和B都有的数据才能查出来 A表和B表结构如下: select *from A inner join B on A.id=B.id; 还可以写成:select *from A join B on A.id=B.id; 或者select *from A , B where A.id=B.id; 取出来的数据是id为1,2,3 2)左连接(左外连接) select *from 表1 left join 表2 on 表1.列=表2.列 左连接查询,按照图表表示如下:取的值是A的全部加上A和B的交集部分 select *from A left join B on A.id=B.id; 还可以写成:select *from A left outer join B on A.id=B.id; 取出来的数据是id为1,2,3,4 3)右连接(右外连接) select *from 表1 right join 表2 on 表1.列=表2.列 右连接查询,按照图表表示如下:取的值是B的全部加上A和B的交集部分 select *from A right join B on A.id=B.id; 还可以写成:select *from A right outer join B on A.id=B.id; 取出来的数据是id为1,2,3 4)全连接 取的是A和B两个表的全部 select *from A left join B on A.id=B.id union select *from A right join B on A.id=B.id; 或者select *from A full join B on A.id=B.id; 6.子查询语句充当查询条件或数据源 1)子查询语句充当查询条件 select *from goods where price > (select avg(price)from goods); ——查询价格高于平均价的商品信息 2)子查询语句充当数据源 select *from (select *from goods go left join category ca on go.typeid=ca.typeid) new where new.company = ''PDD; ——查询所有来自PDD的商品信息,包含商品分类 其中,goods 别名go category别名ca 二、数据类型和约束 1.数据类型 1)整数: int 有符号范围(-2147483648 ~2147483647),⽆符号 (unsigned)范围(0 ~ 4294967295) 2)⼩数: decimal 例如:decimal(5,2) 表示共存5位数,⼩数占2位,整数占3 位 3)字符串: varchar 范围(0~65533),例如:varchar(3) 表示最多存3个字 符,⼀个中⽂或⼀个字 ⺟都占⼀个字符 4)⽇期时间: datetime 范围(1000-01-01 00:00:00 ~ 9999-12-31 23:59:59),例如:'2020-0101 12:29:59' 2.约束 1)主键(primary key) 能唯⼀标识表中的每⼀条记录的属性组 2)⾮空(not null) 此字段不允许填写空值 3)唯⼀(unique) 此字段的值不允许重复 4)默认值(default) 当不填写此值时会使⽤默认值,如果填写时以填写为准 5) 外键(foreign key) ⼀个表中的⼀个字段引⽤另⼀个表的主键 说明: 通过外部数据表的字段, 来控制当前数据表的数据内容变更, 以避免单⽅⾯移除数据, 导致关联表数据产⽣垃圾数据的⼀种⽅法。 注意: 如果⼤量增加外键设置, 会严重影响除数据查询操作以外的其他操作(增/ 删/改)的操作效率。 6)索引 说明: 为字段添加索引,可以⼤幅度提⾼查询语句的执⾏效率。 注意: 如果⼤量增加索引设置, 会严重影响除数据查询操作以外的其他操作(增/ 删/改)的操作效率, 故不⽅便过多添加。 ———————————————— 将内容变为面试题格式 生成个word
08-01
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值