待传输文件被切分成多个部分,按照原排列顺序,每部分文件编号均为一个 正整数(至少含有两个文件)。传输要求为:连续文件编号总和为接收方指定数字 target 的所有文件。请返回所有符合该要求的文件传输组合列表。

注意,返回时需遵循以下规则:

每种组合按照文件编号 升序 排列;

不同组合按照第一个文件编号 升序 排列。

示例 1:

**输入:**target = 12
输出:[[3, 4, 5]]
**解释:**在上述示例中,存在一个连续正整数序列的和为 12,为 [3, 4, 5]。

示例 2:

**输入:**target = 18
输出:[[3,4,5,6],[5,6,7]]
**解释:**在上述示例中,存在两个连续正整数序列的和分别为 18,分别为 [3, 4, 5, 6] 和 [5, 6, 7]。

根据求和公式,一组中最多可有pow(target * 2, 0.5)个元素,由此可以遍历可能的元素个数 i ;

并且如果 i 为奇数,因为除去mid,左右两边元素数量相等,所以target一定为mid的 i 倍

如果 i 为偶数,则mid为左边最右元素,此时 target % i 一定等于 i/2,因为右边最右元素相对于mid会多i/2

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
class Solution {
public:
vector<vector<int>> fileCombination(int target) {
vector<vector<int>> ans;
int maxN = pow(target * 2, 0.5);
for (int i = maxN; i >= 2; i--) {
int mid = target / i;
int midY = target % i;
if (i % 2 == 0 && midY == i / 2) {
vector<int> m;
for (int j = 0; j < i; j++) {
m.push_back(mid - i / 2 + 1 + j);
}
ans.push_back(m);
} else if (i % 2 == 1 && midY == 0) {
vector<int> m;
for (int j = 0; j < i; j++) {
m.push_back(mid - i / 2 + j);
}
ans.push_back(m);
}
}
return ans;
}
};

也可以用双指针来写,初始化 l=1,r=2,

如果 mid < target 则r++

mid > target 则 l++

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
class Solution {
public:
vector<vector<int>> fileCombination(int target) {
vector<vector<int>> ans;
int l = 1, r = 2;
int mid = 3;
while (l < r) {
if (mid == target) {
vector<int> m;
for (int i = l; i <= r; i++) {
m.push_back(i);
}
ans.push_back(m);
}
if (mid < target) {
r += 1;
mid += r;
} else if (mid >= target) {
mid -= l;
l += 1;
}
}
return ans;
}
};