关于 Arrays.binarySearch() 方法的分析
题目:Leetcode 300
Given an unsorted array of integers, find the length of longest increasing subsequence.
Example:
Input: [10,9,2,5,3,7,101,18]
Output: 4
Explanation: The longest increasing subsequence is [2,3,7,101], therefore the length is 4.
Note:
There may be more than one LIS combination, it is only necessary for you to return the length.
Your algorithm should run in O(n2) complexity.
Follow up: Could you improve it to O(n log n) time complexity?
——————————————————————————————————————————————————————————
在这种方法中,我们从左到右扫描数组。
我们还使用一个用所有0初始化的dp数组。这个dp数组用于存储通过包含当前遇到的元素而形成的递增子序列。
在遍历nums数组时,我们继续用到目前为止遇到的元素填充dp数组。对于与j索引(nums[j])相对应的元素,我们通过使用二叉搜索算法 (由于dp数组存储的是增加的子序列,因此可以使用二叉搜索算法)来确定其在dp数组中的正确位置(例如,i索引),并将其插入正确的位置。
需要注意的一点是,对于二叉搜索算法,我们只考虑dp数组中通过在正确位置插入一些元素(始终保持排序)进行更新的部分。因此,只有dp数组中的第i个索引以上的元素才能确定当前元素在其中的位置。由于元素在dp数组中以升序进入其正确position(i),因此迄今为止在该元素中形成的子序列肯定是一个递增的子序列。每当这个位置索引i等于到目前为止LIS的长度(len)时,就意味着我们需要更新len为len=len+1
注意:dp数组不会导致最长子序列的增加,但是dp数组的长度会给您LIS的长度。
Consider the example:
input: [0, 8, 4, 12, 2]
dp: [0]
dp: [0, 8]
dp: [0, 4]
dp: [0, 4, 12]
dp: [0 , 2, 12] 这并不是最长的递增子序列,但是dp数组的长度是最长递增子序列的长度。
注意:Arrays.binarySearch()方法返回索引的搜索键,如果它是包含在数组,其他它返回 (-(insertion point) - 1)。的插入点是点关键将插入数组:第一个元素的索引大于键,或。如果数组中的所有元素都小于指定的键,则为长度。
public class Solution {
public int lengthOfLIS(int[] nums) {
int[] dp = new int[nums.length];
int len = 0;
for (int num : nums) {
int i = Arrays.binarySearch(dp, 0, len, num);
if (i < 0) {
i = -(i + 1);
}
dp[i] = num;
if (i == len) {
len++;
}
}
return len;
}
}
Complexity Analysis
Time complexity :
O(nlogn). Binary search takes nlogn time and it is called n times.
Space complexity :
O(n). dp array of size n is used.