1.第N高的薪水
问题描述:从 Employee
表中检索第 n 高的薪资。如果没有第 n 高的薪资,我们将会返回 null
自己写的代码:
def nth_highest_salary(employee: pd.DataFrame, N: int) -> pd.DataFrame:
employee=employee.drop_duplicates(["salary"])
column_name=f"getNthHighestSalary({N})"
if len(employee["salary"].unique())<N or N<=0:
return pd.DataFrame({column_name:[np.NaN]})
employee=employee.sort_values("salary",ascending=False)
employee.drop("id",axis=1,inplace=True)
result=employee.head(N).tail(1)
result = result.rename(columns={result.columns[0]: column_name})
return result
官方代码:
import pandas as pd
def nth_highest_salary(employee: pd.DataFrame, N: int) -> pd.DataFrame:
df = employee[["salary"]].drop_duplicates()
if len(df) < N or N<=0:
return pd.DataFrame({'getNthHighestSalary('+ str(N) +')': [None]})
df = df.sort_values(by = 'salary', ascending=False).head(N).tail(1)
return df.rename(columns={'salary':'getNthHighestSalary('+ str(N) +')'})
rename
方法期望一个序列(例如列表或字典)作为参数,但这里只传入了一个字符串。在 pandas 中,当你想要重命名单个列名时,你应该使用字典 {old_column_name: new_column_name}
的形式,其中 old_column_name
是当前的列名,new_column_name
是你想要设置的新列名。
2.第178题 分数排名(考察窗口函数)
问题描述:
编写一个解决方案来查询分数的排名。排名按以下规则计算:
- 分数应按从高到低排列。
- 如果两个分数相等,那么两个分数的排名应该相同。
- 在排名相同的分数后,排名数应该是下一个连续的整数。换句话说,排名之间不应该有空缺的数字。
按 score
降序返回结果表。
这个题我写不出来,因为我不了解窗口函数,但是使用子查询的方法我也没有想出来
select score,dense_rank() over (order by score desc) as 'rank' from Scores
知识点学习:窗口函数
窗口函数(也称为OLAP函数或聚合函数)是一种特殊的函数,它们能够对数据集的子集(称为窗口)执行计算,而不会将这些行合并成单个行,这与传统的聚合函数不同。窗口函数在 SQL 查询中非常有用,尤其是在需要在分组或排序的上下文中计算每行的值时。
窗口函数的关键特点:
- 不需要 GROUP BY:与聚合函数不同,窗口函数可以在不使用
GROUP BY
的情况下使用。 - 每行都有自己的结果:它们为查询结果集中的每一行返回一个值。
- 使用 OVER 子句:定义了窗口函数的计算范围,包括分区(PARTITION BY)、排序(ORDER BY)和窗口帧(frame clause)。
常见的窗口函数:
- ROW_NUMBER():为每个窗口内的行分配一个唯一的连续整数。
- RANK():为每个窗口内的行分配一个排名,相同值的行会有相同的排名,排名不连续。
- DENSE_RANK():与 RANK 类似,但排名是连续的。
- LEAD():返回当前行的下一行的值。
- LAG():返回当前行的上一行的值。
- NTILE():将窗口内的行分成指定数量的组。
- SUM():计算窗口内所有行的总和。
- AVG():计算窗口内所有行的平均值。
- MIN() 和 MAX():分别返回窗口内所有行的最小值和最大值。
使用窗口函数的步骤:
- 选择列:确定你想要在查询中使用的列。
- 定义窗口:使用
OVER()
子句定义窗口函数的作用范围。- PARTITION BY:将数据分成不同的分区,每个分区内部独立应用窗口函数。
- ORDER BY:定义窗口内的行的排序顺序。
- frame clause:可选,定义窗口的边界(例如,行的范围或值的范围)。
- 应用窗口函数:在
SELECT
语句中应用窗口函数。
示例 1:
假设有一个名为 Employees
的表,包含 EmployeeID
、Salary
和 Department
列。
SELECT
EmployeeID,
Salary,
Department,
RANK() OVER (PARTITION BY Department ORDER BY Salary DESC) AS SalaryRank
FROM Employees;
这个查询:
- 选择
EmployeeID
、Salary
和Department
列。 - 对每个部门内的员工按薪资降序排列,并为每个员工分配一个排名(
SalaryRank
),使用RANK()
窗口函数。
示例 2:
SELECT
EmployeeID,
Salary,
Department,
SUM(Salary) OVER (PARTITION BY Department) AS DepartmentTotalSalary,
Salary / SUM(Salary) OVER (PARTITION BY Department) AS SalaryRatio
FROM Employees;
这个查询:
- 选择
EmployeeID
、Salary
和Department
列。 - 计算每个部门的总薪资(
DepartmentTotalSalary
)。 - 计算每个员工的薪资占他们所在部门总薪资的比例(
SalaryRatio
)。
子查询解决问题:
select s1.score,
(select count(distinct score) from Scores s2 where s1.score <= s2.score) as 'rank'
from Scores s1
order by score desc
3.NUMPY 创建数组
numpy.empty
numpy.empty 方法用来创建一个指定形状(shape)、数据类型(dtype)且未初始化的数组:
numpy.empty(shape, dtype = float, order = 'C')
返回给定形状和类型的新数组,而无需初始化条目。
参数:prototype - 空数组的形状。dtype(可选) - 数组所需的输出数据类型,例如numpy.int8。默认值为 numpy.float64。order(可选,默认:'C') - 有"C"和"F"两个选项,分别代表,行优先和列优先,在计算机内存中的存储元素的顺序。
numpy.empty_like
numpy.empty 返回形状和类型与给定数组相同的新数组。
numpy.zeros
创建指定大小的数组,数组元素以 0 来填充
numpy.zeros_like
zeros_like返回与给定数组具有相同形状和类型的零数组。
numpy.arange
numpy.arange([ start,] stop,[ step,] dtype = None )
返回给定间隔内的均匀间隔的值。
在半开间隔 (即包括start但不包括stop的间隔)内生成值。对于整数参数,该函数等效于Python内置的 range函数,但返回ndarray而不是列表。[start, stop)
参数 start - 间隔的开始。间隔包括该值。默认起始值为0。stop - 间隔结束。该间隔不包括该值,除非在某些情况下,step不是整数,并且浮点舍入会影响out的长度。step - 值之间的间距。对于任何输出出来,这是两个相邻值之间的距离,默认步长为1。dtype - 输出数组的类型。
返回值:均匀间隔的值的数组。
numpy.linspace
numpy.linspace 函数用于创建一个一维数组,数组是一个等差数列构成的,格式如下:
np.linspace(start, stop, num=50, endpoint=True, retstep=False, dtype=None)
参数start - 序列的起始值。stop - 序列的终止值,如果endpoint为true,该值包含于数列中。num - 要生成的等步长的样本数量,默认为50。endpoint - 该值为 true 时,数列中包含stop值,反之不包含,默认是True。retstep - 如果为 True 时,生成的数组中会显示间距,反之不显示。dtype - ndarray 的数据类型。
4.第14题最长前缀
问题描述:编写一个函数来查找字符串数组中的最长公共前缀。如果不存在公共前缀,返回空字符串 ""
。
通常来说,如果只是遍历一个已知的集合,找出满足条件的元素,并进行相应的操作,那么使用o循环更加简洁。但如果需要在满足某个条件前,不停地重复某些操作,并且没有特定的集合需要去遍历,那么一般则会使用While循环。
自己写的错误代码:
class Solution:
def longestCommonPrefix(self, strs: List[str]) -> str:
if not strs or (len(strs)==1 and strs[0]==""):
return ""
if len(strs)==1:
return strs[0]
if any(s == "" for s in strs):
return ""
shortest=min(strs,key=len)
common=True
for i in range(len(shortest)):
char=shortest[i]
for strgth in strs:
if strgth[i]!=char:
prex=shortest[:i]
common=False
break
if common==False:
break
return prex
正确的代码:
class Solution:
def longestCommonPrefix(self, strs: List[str]) -> str:
if not strs or (len(strs) == 1 and strs[0] == ""):
return ""
if len(strs) == 1:
return strs[0]
if any(s == "" for s in strs):
return ""
shortest = min(strs, key=len)
prefix = ""
for i in range(len(shortest)):
char = shortest[i]
if all(strgth[i] == char for strgth in strs if i < len(strgth)):
prefix += char
else:
return prefix
return prefix
all函数():用于判断给定的可迭代对象中的所有元素是否都为 True
。如果所有元素都为 True
,all()
函数返回 True
;如果至少有一个元素为 False
或者可迭代对象为空,它返回 False
。
5.NUMPY数组索引和切片
数组索引:
NumPy 数组中的索引以 0 开头,这意味着第一个元素的索引为 0,第二个元素的索引为 1。使用负索引从尾开始访问数组。
数组切片:
[start:end];[start:end:step]
不传递 start,则将其视为 0。不传递 end,则视为该维度内数组的长度。不传递 step,则视为 1。
裁切 2-D 数组:
整数数组索引:
x=np.array([[1,2],[3,4],[5,6]])
y=x[[0,1,2],[0,1,0]]
#选取第一行和第一列,第二行和第二列,第三行和第一列的数据。
print(y)
x = np.array([[ 0, 1, 2],[ 3, 4, 5],[ 6, 7, 8],[ 9, 10, 11]])
rows = np.array([[0,0],[3,3]])
cols = np.array([[0,2],[0,2]])
y = x[rows,cols]
#从第一行(索引0)选取第一列(索引0)和第三列(索引2)的元素,即 0 和 2。从第四行(索引3)选取第一列(索引0)和第三列(索引2)的元素,即 9 和 11。
print(y)
布尔索引:
通过一个布尔数组来索引目标数组。布尔索引通过布尔运算(如:比较运算符)来获取符合指定条件的元素的数组。