解题思路
因为表 Address 中的 personId 是表 Person 的外关键字,所以我们可以连接这两个表来获取一个人的地址信息。
考虑到可能不是每个人都有地址信息,我们应该使用 outer join 而不是默认的 inner join。
作者:LeetCode
链接:https://leetcode-cn.com/problems/combine-two-tables/solution/zu-he-liang-ge-biao-by-leetcode/
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
1 2 3 4
| select p.FirstName, p.LastName, a.City, a. State from Person p left join Address a on p.PersonId = a.PersonId;
|
解题方法一:使用子查询和 LIMIT 子句
将不同的薪资按降序排序,然后使用 LIMIT
子句获得第二高的薪资。
然而,如果没有这样的第二最高工资,这个解决方案将被判断为 “错误答案”,因为本表可能只有一项记录。为了克服这个问题,我们可以将其作为临时表。
如果查询结果为 null,原本将返回空数据,建立临时表后变为:select null
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| SELECT (SELECT DISTINCT Salary FROM Employee ORDER BY Salary DESC LIMIT 1 OFFSET 1) AS SecondHighestSalary ;
#作者:LeetCode #链接:https://leetcode-cn.com/problems/second-highest-salary/solution/di-er-gao-de-xin-shui-by-leetcode/ #来源:力扣(LeetCode) #著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
|
解题方法二:使用 IFNULL
和 LIMIT
子句
解决 “NULL” 问题的另一种方法是使用 “IFNULL” 函数,如下所示。
1 2 3 4 5 6 7 8 9 10 11 12 13
| SELECT IFNULL( (SELECT DISTINCT Salary FROM Employee ORDER BY Salary DESC LIMIT 1 OFFSET 1), NULL) AS SecondHighestSalary
#作者:LeetCode #链接:https://leetcode-cn.com/problems/second-highest-salary/solution/di-er-gao-de-xin-shui-by-leetcode/ #来源:力扣(LeetCode) #著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
|
解法一:二分查找
在本题中,我们可以先固定一个值 num
,然后再使用二分查找找 target - num
充分利用了题目中所给的数组是有序数组的条件
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
| class Solution { public int[] twoSum(int[] numbers, int target) { for (int i = 0; i < numbers.length; i++) { int num = numbers[i]; int left = i + 1, right = numbers.length - 1; while (left <= right) { int mid = left + (right - left) / 2; if (numbers[mid] == target - num) { return new int[]{i + 1, mid + 1}; } else if (numbers[mid] < target - num) { left = mid + 1; } else { right = mid - 1; } } } return null; } }
|
- 时间复杂度:O (n logn)
- 空间复杂度:O (1)
解法二:Map
我们可以把数组的元素存储到Map中,然后再查找
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| class Solution { public int[] twoSum(int[] num, int target) { Map<Integer, Integer> map = new HashMap<>(num.length); for (int i = 0; i < num.length; i++) { if (map.get(target - num[i]) != null) { return new int[]{map.get(target - num[i]) + 1, i + 1}; } map.put(num[i], i); } return null; } }
|
解法三:双指针法(最优解)
使用两个指针分别指向数组的头尾,将指针指向的值的和 sum
与 target
作比较:
sum < target
:left++
sum = target:
:return new int[]{left + 1. right + 1}
sum > target
: right++
充分利用了题目中所给的数组是有序数组的条件
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
| public int[] twoSum(int[] numbers, int target) { if (numbers == null) return null; int i = 0, j = numbers.length - 1; while (i < j) { int sum = numbers[i] + numbers[j]; if (sum == target) { return new int[]{i + 1, j + 1}; } else if (sum < target) { i++; } else { j--; } } return null; }
|