21.最长递增子序列问题与扩展
300. 最长递增子序列
已解答
中等
给你一个整数数组 nums
,找到其中最长严格递增子序列的长度。
子序列 是由数组派生而来的序列,删除(或不删除)数组中的元素而不改变其余元素的顺序。例如,[3,6,2,7]
是数组 [0,3,1,6,2,2,7]
的
子序列
。
示例 1:
输入:nums = [10,9,2,5,3,7,101,18] 输出:4 解释:最长递增子序列是 [2,3,7,101],因此长度为 4 。
static int l,r,mid; static int [] arr = new int[2500]; public static int lengthOfLIS(int[] nums) { int n = nums.length; int length = 0; Arrays.fill(arr,2500); arr[0] = nums[0]; for (int i = 1;i<n;i++){ if (nums[i]>arr[length]){ //如果能更新子序列长度数组 arr[++length] = nums[i]; }else{ // l = 0; r = length; int ans = 0; while(l<=r){ mid = l+((r-l)>>1); if (nums[i]>arr[mid]){ l = mid+1; }else{ ans = mid; r = mid-1; } } // if(nums[i]<arr[ans]){ arr[ans] = nums[i]; // } } } return length+1; }
2111. 使数组 K 递增的最少操作次数
已解答
困难
提示
给你一个下标从 0 开始包含 n
个正整数的数组 arr
,和一个正整数 k
。
如果对于每个满足 k <= i <= n-1
的下标 i
,都有 arr[i-k] <= arr[i]
,那么我们称 arr
是 K 递增 的。
-
比方说,
arr = [4, 1, 5, 2, 6, 2]
对于
k = 2
是 K 递增的,因为:
-
arr[0] <= arr[2] (4 <= 5)
-
arr[1] <= arr[3] (1 <= 2)
-
arr[2] <= arr[4] (5 <= 6)
-
arr[3] <= arr[5] (2 <= 2)
-
-
但是,相同的数组
arr
对于k = 1
不是 K 递增的(因为arr[0] > arr[1]
),对于k = 3
也不是 K 递增的(因为arr[0] > arr[3]
)。
每一次 操作 中,你可以选择一个下标 i
并将 arr[i]
改成任意 正整数。
请你返回对于给定的 k
,使数组变成 K 递增的 最少操作次数 。
示例 1:
输入:arr = [5,4,3,2,1], k = 1 输出:4 解释: 对于 k = 1 ,数组最终必须变成非递减的。 可行的 K 递增结果数组为 [5,6,7,8,9],[1,1,1,1,1],[2,2,3,4,4] 。它们都需要 4 次操作。 次优解是将数组变成比方说 [6,7,8,9,10] ,因为需要 5 次操作。 显然我们无法使用少于 4 次操作将数组变成 K 递增的。
static int [] arr1 = new int[100000]; public static int kIncreasing(int[] arr, int k) { int n = arr.length; int count = 0; int length ; for (int i = 0;i<k;i++){ length = (n-i+k-1)/k; int s = lengthOfLIS(arr,i,k); count=count+length-s; } return count; } static int l,r,mid; public static int lengthOfLIS(int[] nums,int start,int k) { int n = nums.length; int length = 0; arr1[0] = nums[start]; for (int i = start+k;i<n;i=i+k){ if (nums[i]>=arr1[length]){ //如果能更新子序列长度数组 arr1[++length] = nums[i]; }else{ // l = 0; r = length; int ans = 0; while(l<=r){ mid = l+((r-l)>>1); if (nums[i]>=arr1[mid]){ l = mid+1; }else{ ans = mid; r = mid-1; } } arr1[ans] = nums[i]; } } return length+1; }
646. 最长数对链
已解答
中等
相关标签
相关企业
给你一个由 n
个数对组成的数对数组 pairs
,其中 pairs[i] = [lefti, righti]
且 lefti < righti
。
现在,我们定义一种 跟随 关系,当且仅当 b < c
时,数对 p2 = [c, d]
才可以跟在 p1 = [a, b]
后面。我们用这种形式来构造 数对链 。
找出并返回能够形成的 最长数对链的长度 。
你不需要用到所有的数对,你可以以任何顺序选择其中的一些数对来构造。
示例 1:
输入:pairs = [[1,2], [2,3], [3,4]] 输出:2 解释:最长的数对链是 [1,2] -> [3,4] 。
static int [] arr = new int[1000]; public static int findLongestChain(int[][] pairs) { int n = pairs.length; //按第一个元素从小到大排序 Arrays.sort(pairs, new Comparator<int[]>() { @Override public int compare(int[] o1, int[] o2) { return o1[0]-o2[0]; } }); arr[0] = pairs[0][1]; int lenngth = 1; int r; int l; int mid; int [] cur; int ans = 0; for (int i = 1;i<n;i++){ cur = pairs[i]; if (cur[0]>arr[lenngth-1]){ arr[lenngth++] = cur[1]; continue; } r = lenngth-1; l = 0; while (l<=r){ mid = l+((r-l)>>1); if (cur[0]>arr[mid]){ l = mid+1; }else{ ans = mid; r = mid-1; } } if (cur[1]<arr[ans]){ arr[ans] = cur[1]; } } return lenngth; }
354. 俄罗斯套娃信封问题
已解答
困难
相关标签
相关企业
给你一个二维整数数组 envelopes
,其中 envelopes[i] = [wi, hi]
,表示第 i
个信封的宽度和高度。
当另一个信封的宽度和高度都比这个信封大的时候,这个信封就可以放进另一个信封里,如同俄罗斯套娃一样。
请计算 最多能有多少个 信封能组成一组“俄罗斯套娃”信封(即可以把一个信封放到另一个信封里面)。
注意:不允许旋转信封。
示例 1:
输入:envelopes = [[5,4],[6,4],[6,7],[2,3]] 输出:3 解释:最多信封的个数为 3, 组合为: [2,3] => [5,4] => [6,7]。
static int r,l,mid; public static int maxEnvelopes(int[][] envelopes) { //先按高度进行排序,因为会出先高度一样的情况,高度一样就按宽度从大到小排序,因为小的后面会会更新大的值, // 如果大的放后面,小的就会被更新,就可以转换为最长递增子序列问题了 Arrays.sort(envelopes, new Comparator<int[]>() { @Override public int compare(int[] o1, int[] o2) { return o1[1] - o2[1]==0 ? o2[0] - o1[0]:o1[1] - o2[1]; } }); int [] ends = new int[envelopes.length]; int length = 1; ends[0] = envelopes[0][0]; for (int i = 1;i<envelopes.length;i++){ if (envelopes[i][0]>ends[length-1]){ ends[length++] = envelopes[i][0]; continue; }else { int ans = 0; l = 0; r = length-1; while (l<=r){ mid = l+((r-l)>>1); if (envelopes[i][0]>ends[mid]){ l = mid+1; }else{ ans = mid; r = mid-1; } } ends[ans] = envelopes[i][0]; } } return length; }