1. 程式人生 > 其它 >【Lintcode】1797. Optimal Utilization

【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[i]+B[j]相等,則取 i i i最小的那個,如果 i i i一樣大了,則繼續取 j j 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]

KA[i]的最大數的下標 s s s;找到之後,再去找滿足 B [ j ] = B [ s ] B[j]=B[s] B[j]=B[s]的最小的 j j j。找到滿足條件的數對之後,再嘗試更新答案。程式碼如下:

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)