【Android春招每日一练】(二十四) LeetCode Hot 5题+SQL语句

概览

LeetCode Hot:合并区间、不同路径、最小路径和、爬楼梯、颜色分类
SQL语句

LeetCode Hot

2.26 合并区间

以数组 intervals 表示若干个区间的集合,其中单个区间为 intervals[i] = [starti, endi] 。请你合并所有重叠的区间,并返回 一个不重叠的区间数组,该数组需恰好覆盖输入中的所有区间 。

示例 1:

输入:intervals = [[1,3],[2,6],[8,10],[15,18]]
输出:[[1,6],[8,10],[15,18]]
解释:区间 [1,3] 和 [2,6] 重叠, 将它们合并为 [1,6].
//排序
//对每个区间左端点升序排序
class Solution {
    public int[][] merge(int[][] intervals) {
        if (intervals.length == 0) {
            return new int[0][2];
        }
        Arrays.sort(intervals, new Comparator<int[]>() {	//重载compare,使排序规则为以数组第一列升序排序
            public int compare(int[] interval1, int[] interval2) {
                return interval1[0] - interval2[0];
            }
        });
        List<int[]> merged = new ArrayList<int[]>();
        for (int i = 0; i < intervals.length; ++i) {
            int L = intervals[i][0], R = intervals[i][1];
            //如果当前区间的左端点在数组 merged 中最后一个区间的右端点之后,那么它们不会重合,我们可以直接将这个区间加入数组 merged 的末尾;
            if (merged.size() == 0 || merged.get(merged.size() - 1)[1] < L) {
                merged.add(new int[]{L, R});
            //否则,它们重合,我们需要用当前区间的右端点更新数组 merged 中最后一个区间的右端点,将其置为二者的较大值。
            } else {
                merged.get(merged.size() - 1)[1] = Math.max(merged.get(merged.size() - 1)[1], R);
            }
        }
        return merged.toArray(new int[merged.size()][]);
    }
}
2.27 不同路径

一个机器人位于一个 m x n 网格的左上角 (起始点在下图中标记为 “Start” )。

机器人每次只能向下或者向右移动一步。机器人试图达到网格的右下角(在下图中标记为 “Finish” )。

问总共有多少条不同的路径?

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-PqDXlJYB-1644493440860)(D:\Typora\img\robot_maze.png)]

示例 1:


输入:m = 3, n = 7
输出:28
//DP
//每个位置的路径 = 该位置左边的路径 + 该位置上边的路径
class Solution {
    public int uniquePaths(int m, int n) {
        int[][] dp = new int[m][n];
        for (int i = 0; i < n; i++) dp[0][i] = 1;	//边界只能往右或者下,只有一种可能
        for (int i = 0; i < m; i++) dp[i][0] = 1;
        for (int i = 1; i < m; i++) {		//状态方程:dp[i][j] = dp[i-1][j] + dp[i][j-1]
            for (int j = 1; j < n; j++) {
                dp[i][j] = dp[i - 1][j] + dp[i][j - 1];
            }
        }
        return dp[m - 1][n - 1];  
    }
}
//优化版本,空间复杂度O(n)
class Solution {
    public int uniquePaths(int m, int n) {
        int[] cur = new int[n];		//只需使用列数的一维数组
        Arrays.fill(cur,1);
        for (int i = 1; i < m;i++){
            for (int j = 1; j < n; j++){
                //cur[j] = cur[j] + cur[j-1]:
                /*
                *cur[j]:以前未更新的路径数,即上一次i循环(上一行)当前列的路径
                *cur[j-1]:更新后,即本行左边一个的路径
                *即左边路径+上边路径,妙啊!
                */
                cur[j] += cur[j-1] ;	
            }
        }
        return cur[n-1];
    }
}
2.28 最小路径和

给定一个包含非负整数的 m x n 网格 grid ,请找出一条从左上角到右下角的路径,使得路径上的数字总和为最小。

说明:每次只能向下或者向右移动一步。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-UxhZWbrd-1644493440864)(D:\Typora\img\minpath.jpg)]

示例 1:

输入:grid = [[1,3,1],[1,5,1],[4,2,1]]
输出:7
解释:因为路径 1→3→1→1→1 的总和最小。
class Solution {
    public int minPathSum(int[][] grid) {
        for(int i = 0; i < grid.length; i++) {
            for(int j = 0; j < grid[0].length; j++) {
                if(i == 0 && j == 0) continue;
                else if(i == 0)  grid[i][j] = grid[i][j - 1] + grid[i][j];
                else if(j == 0)  grid[i][j] = grid[i - 1][j] + grid[i][j];
                else grid[i][j] = Math.min(grid[i - 1][j], grid[i][j - 1]) + grid[i][j];
            }
        }
        return grid[grid.length - 1][grid[0].length - 1];
    }
}
2.29 爬楼梯

同剑指offer8题,青蛙跳台阶,dp算法

2.30

/*
dp[i][j] 代表 word1 到 i 位置转换成 word2 到 j 位置需要最少步数
所以,
当 word1[i] == word2[j],dp[i][j] = dp[i-1][j-1];
当 word1[i] != word2[j],dp[i][j] = min(dp[i-1][j-1], dp[i-1][j], dp[i][j-1]) + 1
其中,dp[i-1][j-1] 表示替换操作,dp[i-1][j] 表示删除操作,dp[i][j-1] 表示插入操作
注意,针对第一行,第一列要单独考虑.
*/
//DP
class Solution {
    public int minDistance(String word1, String word2) {
        int n1 = word1.length();
        int n2 = word2.length();
        int[][] dp = new int[n1 + 1][n2 + 1];
        // 第一行
        for (int j = 1; j <= n2; j++) dp[0][j] = dp[0][j - 1] + 1;
        // 第一列
        for (int i = 1; i <= n1; i++) dp[i][0] = dp[i - 1][0] + 1;

        for (int i = 1; i <= n1; i++) {
            for (int j = 1; j <= n2; j++) {
                if (word1.charAt(i - 1) == word2.charAt(j - 1)) dp[i][j] = dp[i - 1][j - 1];
                else dp[i][j] = Math.min(Math.min(dp[i - 1][j - 1], dp[i][j - 1]), dp[i - 1][j]) + 1;
            }
        }
        return dp[n1][n2];  
    }
}
2.30 颜色分类

给定一个包含红色、白色和蓝色、共 n 个元素的数组 nums ,原地对它们进行排序,使得相同颜色的元素相邻,并按照红色、白色、蓝色顺序排列。

我们使用整数 0、 1 和 2 分别表示红色、白色和蓝色。

必须在不使用库的sort函数的情况下解决这个问题。

示例 1:

输入:nums = [2,0,2,1,1,0]
输出:[0,0,1,1,2,2]
//双指针
//0 挪到最前面,2 挪到最后面
//注意 2 挪完如果换出来的不是 1,那么指针要回退,因为 0 和 2 都是需要再次移动的
class Solution {
    public void sortColors(int[] nums) {
        int n = nums.length;
        if (n < 2) {
            return;
        }
        //双指针
        int p = 0, q = n - 1;
        for (int i = 0; i <= q; ++i) {
            if (nums[i] == 0) {
                nums[i] = nums[p];
                nums[p] = 0;
                ++p;
            }
            if (nums[i] == 2) {
                nums[i] = nums[q];
                nums[q] = 2;
                --q;
                if (nums[i] != 1) {
                    --i;
                }
            }
        }
        return;
    }
}

SQL语句

SQL语句

创建表

CREATE TABLE Student 
( 
	Id INT NOT NULL UNIQUE PRIMARY KEY, 
	Name VARCHAR(20) NOT NULL, 
	Age INT NULL, 
	Gender VARCHAR(4) NULL 
); 

删除表

DROP TABLE <表名>;

清空表

TRUNCATE TABLE <表名>;

修改表

-- 添加学生表`Phone`列 
ALTER TABLE Student ADD Phone VARCHAR(15) NULL; 

-- 删除学生表`Phone`列 
ALTER TABLE Student DROP COLUMN Phone; 

-- 修改学生表`Phone`列 
ALTER TABLE Student MODIFY Phone VARCHAR(13) NULL; 

查询

SELECT [ALL | DISTINCT] <目标列表达式>[,<目标列表达式>]FROM <表名或视图名>[,<表名或视图名>][WHERE <条件表达式>] 
	[GROUP BY <列名> [HAVING <条件表达式>]] 
	[ORDER BY <列名> [ASC|DESC]] 

SQL查询语句的顺序:SELECT、FROM、WHERE、GROUP BY、HAVING、ORDER BY。

SELECT、FROM是必须的,HAVING子句只能与 GROUP BY搭配使用。

SELECT * FROM Student 
	WHERE Id>10 
	GROUP BY Age HAVING AVG(Age) > 20 
	ORDER BY Id DESC 

插入

-- 插入不存在的数据 
INSERT INTO Student (Name,Age,Gender) VALUES ('Andy',30,'女'); 

-- 将查询的数据插入到数据表中 
INSERT INTO Student (Name,Age,Gender) 
	SELECT Name,Age,Gender FROM Student_T WHERE Id >10; 

更新

-- 将Id在(10,100)的Age加1 
UPDATE Student 
	SET Age= Age+1 
	WHERE Id>10 AND Id<100;

删除

-- 删除Id小于10的数据记录 
DELETE FROM Student WHERE Id<10;

索引

索引是一种特殊的查询表,可以被数据库搜索引擎用来加速数据的检索。简单说来,索引就是指向表中数据的指针。数据库的索引同书籍后面的索引非常相像。

例如,如果想要查阅一本书中与某个特定主题相关的所有页面,你会先去查询索引(索引按照字母表顺序列出了所有主题),然后从索引中找到一页或者多页与该主题相关的页面。

索引能够提高 SELECT 查询和 WHERE 子句的速度,但是却降低了包含 UPDATE语句或 INSERT 语句的数据输入过程的速度。索引的创建与删除不会对表中的数据产生影响。

-- 建立学生表索引:单一字段Id索引倒序 
CREATE UNIQUE INDEX INDEX_SId ON Student (Id DESC); 

-- 建立学生表索引:多个字段Id、Name索引倒序 
CREATE UNIQUE INDEX INDEX_SId_SName ON Student (Id DESC,Name DESC); 

UNIQUE:表明此索引的每一个索引值只对应唯一的数据记录 CLUSTER:表明建立的索引是聚集索引 次序:可选ASC(升序)或DESC(降序),默认ASC

-- 删除学生表索引 
INDEX_SId DROP INDEX INDEX_SId;

视图

视图无非就是存储在数据库中并具有名字的 SQL 语句,或者说是以预定义的 SQL查询的形式存在的数据表的成分。

视图可以包含表中的所有列,或者仅包含选定的列。视图可以创建自一个或者多个表,这取决于创建该视图的 SQL 语句的写法。

视图,一种虚拟的表,允许用户执行以下操作:

  • 以用户或者某些类型的用户感觉自然或者直观的方式来组织数据;

  • 限制对数据的访问,从而使得用户仅能够看到或者修改(某些情况下)他们需要的数据;

  • 从多个表中汇总数据,以产生报表。

创建视图

CREATE VIEW <视图名> 
	AS SELECT 查询子句 
	[WITH CHECK OPTION]

查询子句:子查询可以是任何SELECT语句,但是常不允许含有 ORDER BY 子句和 DISTINCT 短语;

WITH CHECK OPTION:表示对UPDATE、INSERT、DELETE操作时要保证更新。

CREATE VIEW VIEW_Stu_Man 
	AS SELECT * FROM Student WHERE Gender = '男' 
	WITH CHECK OPTION;

删除视图

DROP VIEW <视图名>;

ORDER BY

ORDER BY 子句根据一列或者多列的值,按照升序或者降序排列数据。某些数据库默认以升序排列查询结果

SELECT [ALL | DISTINCT] <目标列表达式>[,<目标列表达式>]FROM <表名或视图名>[,<表名或视图名>][WHERE <条件表达式>] 
	[ORDER BY <列名>] [ASC | DESC]; 

LIKE

LIKE 子句通过通配符来将一个值同其他相似的值作比较。可以同 LIKE 运算符一起使用的通配符有两个:

%:替代 0 个或多个字符

_:替代一个字符

SELECT FROM table_name 
WHERE column LIKE 'XXXX%'

HAVING

HAVING 子句使你能够指定过滤条件,从而控制查询结果中哪些组可以出现在最终结果里面。

WHERE 子句对被选择的列施加条件,而 HAVING 子句则对 GROUP BY 子句所产生的组施加条件。

SELECT ID, NAME, AGE, ADDRESS, SALARY 
FROM CUSTOMERS 
GROUP BY age 
HAVING COUNT(age) >= 2;

DISTINCT

DISTINCT 关键字同 SELECT 语句一起使用,可以去除所有重复记录,只返回唯一项。

SELECT DISTINCT SALARY 
FROM CUSTOMERS 
ORDER BY SALARY

AND和OR

将 N 个条件用 AND 运算符结合在一起。对于 SQL 语句要执行的动作来说——无论是事务还是查询,AND 运算符连接的所有条件都必须为 TRUE。

SELECT ID, NAME, SALARY 
FROM CUSTOMERS 
WHERE SALARY > 2000 AND age < 25;

对于 SQL 语句要执行的动作来说——无论是事务还是查询,OR 运算符连接的所有条件中只需要有一个为 TRUE 即可。

SELECT ID, NAME, SALARY 
FROM CUSTOMERS 
WHERE SALARY > 2000 OR age < 25; 

UNION

UNION 子句/运算符用于将两个或者更多的 SELECT 语句的运算结果组合起来。在使用 UNION 的时候,每个 SELECT 语句必须有相同数量的选中列、相同数量的列表达式、相同的数据类型,并且它们出现的次序要一致,不过长度不一定要相同。

SELECT Txn_Date FROM Store_Information 
UNION 
SELECT Txn_Date FROM Internet_Sales;

UNION ALL 子句:

UNION ALL 运算符用于将两个 SELECT 语句的结果组合在一起,重复行也包含在内。

INTERSECT子句:

用于组合两个 SELECT 语句,但是只返回两个 SELECT 语句的结果中都有的行。

EXCEPT 子句:

组合两个 SELECT 语句,并将第一个 SELECT 语句的结果中存在,但是第二个SELECT 语句的结果中不存在的行返回。

JOIN

连接(JOIN) 子句用于将数据库中两个或者两个以上表中的记录组合起来。连接通过共有值将不同表中的字段组合在一起。

SQL 中有多种不同的连接:

内连接(INNER JOIN):当两个表中都存在匹配时,才返回行。

左连接(LEFT JOIN):返回左表中的所有行,如果左表中行在右表中没有匹配行,则结果中右表中的列返回空值。

右连接(RIGHT JOIN):恰与左连接相反,返回右表中的所有行,如果右表中行在左表中没有匹配行,则结果中左表中的列返回空值。

全连接(FULL JOIN):返回左表和右表中的所有行。当某行在另一表中没有匹配行,则另一表中的列返回空值

SELECT ID, NAME, AMOUNT, DATE 
FROM CUSTOMERS INNER 
JOIN ORDERS 
ON CUSTOMERS.ID = ORDERS.CUSTOMER_ID;

总结

1.算法真的很奇妙,只有深入理解它才能体会到它的美妙,27题用DP求不同路径时,使用一维数组存储路径数非常巧妙;
2.今天复习了SQL语句,因为是客户端,所以数据库要求不算高,只复习了基本得知识点。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

leisure-ZL

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值