LeetCode-Algorithms #004 Median Of Two Sorted Arrays, Database #178 Rank Scores

 LeetCode-Algorithms #004 Median Of Two Sorted Arrays

给定两个已经完成排序的整数数组, 数组长度分别为m和n. 找到这两个数组的中位数, 算法的时间复杂度不超过O(log(m+n)).

这两个数组不会都是空的.

 1 class Solution {
 2     public double findMedianSortedArrays(int[] nums1, int[] nums2) {
 3         //创建一个结果数组
 4         int[] result;
 5         //处理nums1或nums2为空的特殊情况
 6         if(nums1==null){
 7             result=nums2;
 8         }else if(nums2==null){
 9             result=nums1;
10         }
11         //都非空时把两个数组拼接起来并重新排序
12         else{
13             result = new int[nums1.length+nums2.length];
14             System.arraycopy(nums1, 0, result, 0, nums1.length);
15             System.arraycopy(nums2, 0, result, nums1.length, nums2.length);
16             Arrays.sort(result);
17         }
18         //求出并返回中位数
19         int l = result.length;
20         if(l%2==0){
21             double ans = (double) (result[l/2] + result[l/2 - 1])/2;
22             return ans;
23         } else {
24             double ans = result[l/2];
25             return ans;
26         }
27     }
28 }

我的想法就是把两个数组拼到一起再重新排序, 但这显然是个笨办法, 但这么做好像时间复杂度上是符合要求的, 因为也只用了一次拼接和两次arraycopy和一次sort

最后虽然顺利通过了, 但显然不是题目设定上想让你采取的方法

回头看LeetCode提供的一种解答思路, 想法上是把两个数组都分割成两部分:

如果我们能够满足上面这两个条件, 即左右两边元素个数相同, 及左侧最大值小于右侧最小值

由于两个原数组本身就是排序完成的, 那么中位数自然就找到了

藉由这种思路, 我们可以知道需要四个变量, i, j表示划分原数组时选择的位置, m, n表示原数组的长度,

以及这四个变量间的关系, 最后用二分查找法找到合适的i,j 找到中位数.

原文的解析实在太长, 这里就只贴上地址和代码:
https://leetcode.com/problems/median-of-two-sorted-arrays/solution/

 1 class Solution {
 2     public double findMedianSortedArrays(int[] A, int[] B) {
 3         int m = A.length;
 4         int n = B.length;
 5         if (m > n) { // to ensure m<=n
 6             int[] temp = A; A = B; B = temp;
 7             int tmp = m; m = n; n = tmp;
 8         }
 9         int iMin = 0, iMax = m, halfLen = (m + n + 1) / 2;
10         while (iMin <= iMax) {
11             int i = (iMin + iMax) / 2;
12             int j = halfLen - i;
13             if (i < iMax && B[j-1] > A[i]){
14                 iMin = i + 1; // i is too small
15             }
16             else if (i > iMin && A[i-1] > B[j]) {
17                 iMax = i - 1; // i is too big
18             }
19             else { // i is perfect
20                 int maxLeft = 0;
21                 if (i == 0) { maxLeft = B[j-1]; }
22                 else if (j == 0) { maxLeft = A[i-1]; }
23                 else { maxLeft = Math.max(A[i-1], B[j-1]); }
24                 if ( (m + n) % 2 == 1 ) { return maxLeft; }
25 
26                 int minRight = 0;
27                 if (i == m) { minRight = B[j]; }
28                 else if (j == n) { minRight = A[i]; }
29                 else { minRight = Math.min(B[j], A[i]); }
30 
31                 return (maxLeft + minRight) / 2.0;
32             }
33         }
34         return 0.0;
35     }
36 }

LeetCode-Database #178 Rank Scores

 

为分数排名, 同分的显示相同的名次, 具体可以看图中的例子

嗯... 

简单来说就是

我不会...

看两个答案吧:

SELECT t1.Score,
-- 这个思路不错, 用一个自连接获取排名
(
SELECT COUNT(DISTINCT t2.Score)+1
FROM Scores t2
WHERE t1.Score < t2.Score
) AS Rank
FROM Scores t1
ORDER BY t1.Score DESC
-- 思路是如果本行分数和上一行不同, 排名就加一
SELECT
Score, @rank := @rank + (@prev <> (@prev := Score)) Rank FROM Scores, (Select @rank := 0, @prev := -1) tmp ORDER BY Score desc

点了不少, 不过主要就是这两类写法, 下面那个我确实不太熟悉, 包括@变量 := 值这种写法都忘得差不多了...

SQL这边稍微复杂一点的应用就没什么思路, 借这个机会多练习吧.

猜你喜欢

转载自www.cnblogs.com/chang4/p/9728434.html