题目描述
There are n soldiers standing in a line. Each soldier is assigned a unique rating value.
You have to form a team of 3 soldiers amongst them under the following rules:
Choose 3 soldiers with index (i, j, k) with rating (rating[i], rating[j], rating[k]). A team is valid if: (rating[i] < rating[j] < rating[k]) or (rating[i] > rating[j] > rating[k]) where (0 <= i < j < k < n). Return the number of teams you can form given the conditions. (soldiers can be part of multiple teams).
例子
例子 1
Input: rating = [2,5,3,4,1] Output: 3 Explanation: We can form three teams given the conditions. (2,3,4), (5,4,1), (5,3,1).
例子 2
Input: rating = [2,1,3] Output: 0 Explanation: We can’t form any team given the conditions.
例子 3
Input: rating = [1,2,3,4] Output: 4
限制条件
n == rating.length
1 <= n <= 200
1 <= rating[i] <= 10^5
解题思路
方法一
看数据规模在 200 以下首先可以想到用暴力解法,直接用三层 for
循环遍历所有的可能性求可能的解;另外我首先想的方法是用回溯+剪枝
,但是在这道题里面每个组规定的组员是固定,而且只有三个。在这种情况下用三层for
循环能够避免递归产生的开销,更加合适;代码比较简单就不写了。
- 时间复杂度: O(n^3)
- 空间复杂度: O(1)
方法二
这道题还有一种比较巧妙的解法,我是参考花花酱的题解视频写出来的,这里分享一下。首先假设我们选中在 i 位置的士兵作为队伍的中间人;那么对他而言,我们首先找出他左边排名比他小的,假设有 l 个;右边排名比他大的,假设有 r 个。那么有:
- 对于升序的情况,组合有:
l * r
种 - 对于逆序的情况,左边有
i - l
个,右边有N - 1 - l
个,所以有(i - l) * (N - 1 - l)
种 - 最后相加一个
上面是针对一个士兵的,那么我们遍历一遍取所有士兵作为中间值就可以求得总的解数量,代码如下:
class Solution {
public:
int numTeams(vector<int>& rating) {
int counts = 0;
for (int i = 0; i < rating.size(); i++) {
int left = 0;
int right = 0;
for (int j = 0; j < rating.size(); j++) {
if (j < i && rating[j] < rating[i]) {
left++;
}
if (j > i && rating[j] > rating[i]) {
right++;
}
// we have left rating is less than rating[i] and right ratings larger than rating[i]
}
counts += left * right;
counts += (i - left) * (rating.size() - 1 - i - right);
}
return counts;
}
};
- 时间复杂度: O(n^2)
- 空间复杂度: O(1)