力扣(数据库&&哈希表)例题(day04)

185. 部门工资前三高的所有员工

表: Employee

+--------------+---------+
| Column Name  | Type    |
+--------------+---------+
| id           | int     |
| name         | varchar |
| salary       | int     |
| departmentId | int     |
+--------------+---------+
id 是该表的主键列(具有唯一值的列)。
departmentId 是 Department 表中 ID 的外键(reference 列)。
该表的每一行都表示员工的ID、姓名和工资。它还包含了他们部门的ID。

表: Department

+-------------+---------+
| Column Name | Type    |
+-------------+---------+
| id          | int     |
| name        | varchar |
+-------------+---------+
id 是该表的主键列(具有唯一值的列)。
该表的每一行表示部门ID和部门名。

公司的主管们感兴趣的是公司每个部门中谁赚的钱最多。一个部门的 高收入者 是指一个员工的工资在该部门的 不同 工资中 排名前三 。

编写解决方案,找出每个部门中 收入高的员工 。

以 任意顺序 返回结果表。

select  Department, Employee, Salary
from (
    select d.name as 'Department',e.name as 'Employee',e.Salary as 'Salary',dense_rank()over(partition by departmentId order by salary desc )ranks
    from Employee e 
    left join Department d
    on e.departmentId=d.id
)t
where ranks<=3

开窗dense_rank() over(partition by sth order by sth),先分组然后排序取前三,rank 是跳次排序 1,1,1,4dense_rank是不跳次排序1,1,1,2row_number是顺序1,2,3,4 在之前的文章有提过

197. 上升的温度

表: Weather

+---------------+---------+
| Column Name   | Type    |
+---------------+---------+
| id            | int     |
| recordDate    | date    |
| temperature   | int     |
+---------------+---------+
id 是该表具有唯一值的列。
没有具有相同 recordDate 的不同行。
该表包含特定日期的温度信息

编写解决方案,找出与之前(昨天的)日期相比温度更高的所有日期的 id 。

返回结果 无顺序要求 。

SELECT b.Id
FROM Weather as a,Weather as b
WHERE a.Temperature < b.Temperature 
and DATEDIFF(a.RecordDate,b.RecordDate) = -1;

 这个比较简单,很基础

196. 删除重复的电子邮箱

表: Person

+-------------+---------+
| Column Name | Type    |
+-------------+---------+
| id          | int     |
| email       | varchar |
+-------------+---------+
id 是该表的主键列(具有唯一值的列)。
该表的每一行包含一封电子邮件。电子邮件将不包含大写字母。

编写解决方案 删除 所有重复的电子邮件,只保留一个具有最小 id 的唯一电子邮件。

(对于 SQL 用户,请注意你应该编写一个 DELETE 语句而不是 SELECT 语句。)

(对于 Pandas 用户,请注意你应该直接修改 Person 表。)

运行脚本后,显示的答案是 Person 表。驱动程序将首先编译并运行您的代码片段,然后再显示 Person 表。Person 表的最终顺序 无关紧要 

DELETE p1
FROM Person p1
JOIN Person p2 ON p1.email = p2.email
WHERE p1.id > p2.id;

也很简单,连接两张表,条件是他们邮件相同,选择id小的在前面,大的被删除就解决了

13. 罗马数字转整数

罗马数字包含以下七种字符: I, V, X, LCD 和 M

字符          数值
I             1
V             5
X             10
L             50
C             100
D             500
M             1000

例如, 罗马数字 2 写做 II ,即为两个并列的 1 。12 写做 XII ,即为 X + II 。 27 写做  XXVII, 即为 XX + V + II 。

通常情况下,罗马数字中小的数字在大的数字的右边。但也存在特例,例如 4 不写做 IIII,而是 IV。数字 1 在数字 5 的左边,所表示的数等于大数 5 减小数 1 得到的数值 4 。同样地,数字 9 表示为 IX。这个特殊的规则只适用于以下六种情况:

  • I 可以放在 V (5) 和 X (10) 的左边,来表示 4 和 9。
  • X 可以放在 L (50) 和 C (100) 的左边,来表示 40 和 90。 
  • C 可以放在 D (500) 和 M (1000) 的左边,来表示 400 和 900。

给定一个罗马数字,将其转换成整数。

class Solution {
 private static final Map<Character,Integer> sv=new HashMap<>();
        static{
         sv.put('I',1); 
         sv.put('V', 5);
         sv.put('X', 10);
         sv.put('L', 50);
         sv.put('C', 100);
         sv.put('D', 500);
         sv.put('M', 1000);
    }
    public int romanToInt(String s) {
        int a = 0;
        int n =s.length();
        for(int i =0;i<n;i++){
            int v = sv.get(s.charAt(i));
            if(i<n-1 && v<sv.get(s.charAt(i+1))){
                a -= v;
            }else{
                a +=v;
            }
        }
        return a;
    }
}

用哈希表来存储键值对,输入字符串,进遍历 如果小于后面的值用减法,大于用加法 

 if(i<n-1 && v<sv.get(s.charAt(i+1)))

  • 如果条件为真

    • 当前字符的值小于它后面字符的值,说明这是一个减法的情况。例如,在罗马数字中,“IV”表示4,因为“I”(1)在“V”(5)之前,所以需要从结果中减去1。

    • 因此,执行 ans -= value,从结果中减去当前字符的值。

  • 如果条件为假

    • 当前字符的值大于或等于它后面字符的值,说明这是一个加法的情况。例如,“VI”表示6,因为“I”(1)在“V”(5)之后,或者“V”(5)后面没有更小的数字,所以需要将当前字符的值加到结果中。

    • 因此,执行 ans += value,将当前字符的值加到结果中。

17. 电话号码的字母组合

给定一个仅包含数字 2-9 的字符串,返回所有它能表示的字母组合。答案可以按 任意顺序 返回。

给出数字到字母的映射如下(与电话按键相同)。注意 1 不对应任何字母。

示例 1:

输入:digits = "23"
输出:["ad","ae","af","bd","be","bf","cd","ce","cf"]

示例 2:

输入:digits = ""
输出:[]

示例 3:

输入:digits = "2"
输出:["a","b","c"]
class Solution {

    public List<String> letterCombinations(String digits) {
      List<String> combinations = new ArrayList<String>();
        if (digits.length() == 0) {
            return combinations;
        } Map<Character, String> phoneMap = new HashMap<Character, String>() {{
            put('2', "abc");
            put('3', "def");
            put('4', "ghi");
            put('5', "jkl");
            put('6', "mno");
            put('7', "pqrs");
            put('8', "tuv");
            put('9', "wxyz");
        }};
        backtrack(combinations, phoneMap, digits, 0, new StringBuffer());
        return combinations;
      
    }

    public void backtrack(List<String> combinations, Map<Character, String> phoneMap, String digits, int index, StringBuffer combination) {
        if (index == digits.length()) {
            combinations.add(combination.toString());
        } else {
            char digit = digits.charAt(index);
             String letters = phoneMap.get(digit);
             int lettersCount = letters.length();
            for (int i = 0; i < lettersCount; i++) {
                combination.append(letters.charAt(i));
                backtrack(combinations, phoneMap, digits, index + 1, combination);
                combination.deleteCharAt(index);
            }
        }
    }

}

 终止条件的逻辑

index == digits.length() 时,意味着:

  • 所有数字字符都已经被处理完毕:因为 index 从 0 开始,每处理一个数字字符,index 就加1。当 index 等于 digits.length() 时,说明已经处理完所有数字字符。

  • 当前构建的字母组合是完整的:因为每个数字字符都对应一个字母,且每个字母都被添加到了 combination 中。当所有数字字符都处理完毕时,combination 中的字母数量正好等于 digits 的长度,说明已经构建了一个完整的字母组合。

具体例子

假设输入的数字字符串是 "23"

  • digits.length() = 2,表示有两个数字字符需要处理。

  • 初始时,index = 0,表示从第一个数字字符 '2' 开始处理。

  • 每次递归调用 backtrack 时,index 加1:

    • 第一次递归:index = 0,处理 '2'

    • 第二次递归:index = 1,处理 '3'

    • 第三次递归:index = 2,此时 index == digits.length(),说明所有数字字符都已处理完毕。

index == 2 时,combination 中的字母组合长度为 2(与 digits.length() 相等),说明已经构建了一个完整的字母组合

递归调用

backtrack(combinations, phoneMap, digits, index + 1, combination);
  • 递归调用 backtrack 函数,处理下一个数字字符。

  • index + 1 表示移动到下一个数字字符。

  • 递归调用时,combination 已经包含了当前数字对应的字母,因此递归调用会继续构建更长的组合。

5. 回溯操作

combination.deleteCharAt(index);
  • 在递归调用返回后,需要进行回溯操作。

  • combination.deleteCharAt(index) 用于移除当前组合中最后一个添加的字母(即当前数字对应的字母)。

  • 这一步是为了恢复 combination 的状态,以便尝试下一个字母。

欧克,就到这哈

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值