一、题目
题目:
某部门计划通过结队编程来进行项目开发,已知该部门有 N 名员工,每个员工有独一无二的职级,每三个员工形成一个小组进行结队编程,结队分组规则如下:
从部门中选出序号分别为 i、j、k 的3名员工,他们的职级分贝为 level[i],level[j],level[k],结队小组满足 level[i] < level[j] < level[k] 或者 level[i] > level[j] > level[k]。其中 0 ≤ i < j < k < n。
请你按上述条件计算可能组合的小组数量。同一员工可以参加多个小组。
输入:
第一行输入:员工总数 n
第二行输入:按序号依次排列的员工的职级 level,中间用空格隔开
限制:
1 ≤ n ≤ 6000
1 ≤ level[i] ≤ 10^5
例子:
4
1 2 3 4
输出:
可能结队的小组数量
例子:
4
二、题解
题目看起来有点复杂,理解了其实就是一个 n 个数中取 k 个数的组合数问题。level[i] < level[j] < level[k]和 level[i] > level[j] > level[k] 其实是一个。 组合数就是套回溯模板了。
package org.stone.study.algo.ex202411;
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
public class PairProgrammingNum {
public static void main(String[] args) {
int n = 4;
int[] arr = new int[] {1, 2, 3, 4};
int ans = pairProgrammingNum(n, arr, 3);
System.out.println(ans);
}
/**
* 从 n 个数中选 3 个数
* @param n:一共 n 个数
* @param arr
* @param k:选 3 个数
* @return
*/
public static int pairProgrammingNum(int n, int[] arr, int k) {
List<List<Integer>> ans = new LinkedList<>();
List<Integer> temp = new LinkedList<>();
backtrack(arr, 0, temp, ans, k);
System.out.println(ans);
return ans.size();
}
/**
* 回溯法求所有组合
* @param arr
* @param start
* @param temp
* @param ans
* @param k
*/
public static void backtrack(int[] arr, int start, List<Integer> temp, List<List<Integer>> ans, int k) {
if (temp.size() == k) {
ans.add(new ArrayList<>(temp));
return;
}
for (int i = start; i < arr.length; i++) {
temp.add(arr[i]);
backtrack(arr, i + 1, temp, ans, k);
temp.remove(temp.size() - 1);
}
}
}