给你一个数组nums,请你从中抽取一个子序列,满足该子序列的元素之和严格大于未包含在该子序列中的各元素之和。
如果存在多个解决方案,只需返回长度最小的子序列。如果仍然有多个解决方案,则返回元素之和最大的子序列。
示例1:
输入:nums=[4,4,7,6,7]
输出:[7,7,6]
解释:子序列[7,7]之和是14,[4,4,6]之和是14,不满足条件,所以返回[7,7,6]
这道题就是一道排序题,整体流程如下:
基本代码实现如下:
-
- import java.util.ArrayList;
- import java.util.Arrays;
- import java.util.List;
-
- class Solution1 {
- public List
minSubsequence(int[] nums) { -
- List
list = new ArrayList<>(); - Arrays.sort(nums);
-
- int sum = 0;
- for(int i=0;i
- sum += nums[i];
- }
-
- int rightSum = 0;
- for(int i=nums.length-1;i>=0;i--) {
- rightSum += nums[i];
- list.add(nums[i]);
- if(sum - rightSum< rightSum) {
- return list;
- }
-
- }
-
- return list;
- }
- }
上述代码实现是标准的解法,但是还可以做优化,降低耗时。这里我使用计数排序,通过计数排序,降低时间复杂度。
要使用计数排序,需要先知道整个数据规模,题目给定的数据规模:
1 <= nums.length <= 5001 <= nums[i] <= 100
下面来看看计数排序算法的实现思路:

如上图所示,由于上述代码的最大值是14,所以准备长度为15的数组。计数统计代码如下:
public int[] countSort(int[] array, int max) {
// 做频次统计
int[] countArray = new int[max + 1];
for (int num : array) {
countArray[num]++;
}
// 还原排序结果
int[] res = new int[array.length];
int index = 0;
for (int j = 0; j < countArray.length; j++) {
int count = countArray[j];
if (count > 0) {
for (int i = 0; i < count; i++) {
res[index++] = j;
}
}
}
return res;
}
//1,8,9,14,7,6,9,12,10,13,8,4,2,9,8
public static void main(String[] args) {
Solution1 solution = new Solution1();
int max = 14;
int[] array = new int[]{1, 8, 9, 14, 7, 6, 9, 12, 10, 13, 8, 4, 2, 9, 8};
System.out.println(Arrays.toString(solution.countSort(array, max)));
}
根据上述排序代码实现,可以对这道题代码实现做优化,优化思路就是通过计数排序,降低时间复杂度。代码实现如下:
- import java.util.ArrayList;
- import java.util.Arrays;
- import java.util.List;
-
- class Solution {
- public List
minSubsequence(int[] nums) { -
- // 直接取长度为101的数组
- int[] array = new int[101];
- // 计数总和
- int sum = 0;
- for (int num : nums) {
- array[num]++;
- sum += num;
- }
-
- int half = sum / 2 + 1;
- int halfSum = 0;
- List
res = new ArrayList<>(); - for (int i = 100; i >= 0; i--) {
- if (array[i] > 0) {
- for (int j = 0; j < array[i]; j++) {
- halfSum += i;
- res.add(i);
- if (halfSum >= half) {
- break;
- }
- }
- if (halfSum >= half) {
- break;
- }
- }
- }
- return res;
- }
- }
总结
这道题是一道普通的排序题目,但如果要时间复杂度最优,还是需要调优排序算法;我这里使用了计数排序,将O(n*log n) 的时间复杂度降低到了O(n),完成对代码的优化。优化效果如下:

欢迎有更好解法的同学回复解题思路。