待传输文件被切分成多个部分,按照原排列顺序,每部分文件编号均为一个 正整数(至少含有两个文件)。传输要求为:连续文件编号总和为接收方指定数字 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; } };
|