【Lintcode】1797. Optimal Utilization
技術標籤:# 二分、位運算與數學演算法leetcodejava
題目地址:
https://www.lintcode.com/problem/optimalutilization/description
給定兩個陣列
A
A
A和
B
B
B,再給定一個數
K
K
K,找到
i
i
i和
j
j
j滿足下面的條件:
1、
A
[
i
]
+
B
[
j
]
≤
K
A[i]+B[j]\le K
A[i]+B[j]≤K;
2、
A
[
i
]
+
B
[
j
]
A[i]+B[j]
A[i]+B[j]儘可能的大;
3、如果存在若干
(
i
,
j
)
(i,j)
(i,j)使得
A
[
i
]
+
B
[
j
]
A[i]+B[j]
如果
A
A
A和
B
B
B某個為空,則返回空陣列。
可以用二分,對每個
A
[
i
]
A[i]
A[i],都去找
j
j
j使得
A
[
i
]
+
B
[
j
]
A[i]+B[j]
A[i]+B[j]並且
B
[
j
]
B[j]
B[j]儘可能大,
j
j
j儘可能小。步驟是這樣的:對於
A
[
i
]
A[i]
A[i],先從
B
B
B裡找到使得
A
[
i
]
+
B
[
j
]
≤
K
A[i]+B[j]\le K
A[i]+B[j]≤K並且最大的數,也就是找小於等於
K
−
A
[
i
]
K-A[i]
public class Solution {
/**
* @param A: a integer sorted array
* @param B: a integer sorted array
* @param K: a integer
* @return: return a pair of index
*/
public int[] optimalUtilization(int[] A, int[] B, int K) {
// write your code here
if (A.length == 0 || B.length == 0) {
return new int[0];
}
int[] res = new int[2];
int curSum = Integer.MIN_VALUE;
for (int i = 0; i < A.length; i++) {
// 找到B裡最大的滿足A[i] + B[idx] <= K的idx,並且idx儘量小
int idx = binarySearch(B, K - A[i]);
// 如果沒找到,那麼繼續遍歷A只會更找不到,所以退出迴圈
if (idx == -1) {
break;
}
// 求得了更大的和了,則更新答案
if (A[i] + B[idx] > curSum) {
curSum = A[i] + B[idx];
res[0] = i;
res[1] = idx;
}
}
return res;
}
private int binarySearch(int[] B, int max) {
int l = 0, r = B.length - 1;
while (l < r) {
int m = l + (r - l + 1 >> 1);
if (B[m] <= max) {
l = m;
} else {
r = m - 1;
}
}
if (B[l] > max) {
return -1;
}
int tmp = B[l];
r = l;
l = 0;
while (l < r) {
int m = l + (r - l >> 1);
if (B[m] >= tmp) {
r = m;
} else {
l = m + 1;
}
}
return l;
}
}
時間複雜度 O ( l A log l B ) O(l_A\log l_B) O(lAloglB),空間 O ( 1 ) O(1) O(1)。