鱼C论坛

 找回密码
 立即注册
查看: 3381|回复: 4

[已解决]如何求数列的子数列个数

[复制链接]
发表于 2019-4-16 10:42:57 | 显示全部楼层 |阅读模式
55鱼币
本帖最后由 RIXO 于 2019-4-16 10:44 编辑

数列就是一串数字的集合,子数列就是他不改变相对顺序下的子集

例如 (1,2,1)
子数列为 (1)(2)(1,2)(2,1)(1,1)(1,2,1)
个数为6

我的数列是无序数列,且里面的每个值都小于等于5,即可能值为 0,1,2,3,4,5

想求一个效率高一点的算法。

如果可以尽量用C和C++,java我还没学。
最佳答案
2019-4-16 10:42:58
本帖最后由 Croper 于 2019-4-16 18:01 编辑

使用动态规划解决,效率要高得多
  1. #include <vector>
  2. #include <unordered_map>
  3. #include <iostream>

  4. using namespace std;
  5. //动态规划
  6. //从size为1的子集开始,now记录以当前节点结束的新增子集的数目
  7. //当size增加时,now变为pre,并通过pre推出新的now


  8. int GetSubArrCount(vector<int> v) {
  9.         vector<int> pre(v.size()+1, 0);
  10.         pre[0] = 1;              //当子集的size为0时,只有1个子集,空集
  11.         int sum = 0;         
  12.         for (int i = 0; i <= v.size(); ++i) {
  13.                 vector<int> now(v.size() - i, 0);
  14.                 for (int j = 0; j < pre.size()-1; ++j) {  //遍历pre的元素,当元素不为0时,考虑此元素与之后的每一个不重复的元素都能构成新的不重复子集
  15.                         if (pre[j] == 0) continue;
  16.                         unordered_map<int, bool> map;
  17.                         for (int k = 0; k < pre.size()-1 - j; ++k) {
  18.                                 int a = v[i + j + k];
  19.                                 if (map[a] == false) {
  20.                                         map[a] = true;
  21.                                         now[j + k] += pre[j];
  22.                                         sum += pre[j];
  23.                                 }
  24.                         }
  25.                 }
  26.                 pre = move(now);
  27.         }
  28.         return sum;
  29. }
  30. int main() {
  31.         vector<int> v = { 1,3,2,5,3,1,4,2,5};
  32.         int i = GetSubArrCount(v);
  33.         cout << i;
  34.         system("pause");
  35. }
复制代码

最佳答案

查看完整内容

使用动态规划解决,效率要高得多
小甲鱼最新课程 -> https://ilovefishc.com
回复

使用道具 举报

发表于 2019-4-16 10:42:58 | 显示全部楼层    本楼为最佳答案   
本帖最后由 Croper 于 2019-4-16 18:01 编辑

使用动态规划解决,效率要高得多
  1. #include <vector>
  2. #include <unordered_map>
  3. #include <iostream>

  4. using namespace std;
  5. //动态规划
  6. //从size为1的子集开始,now记录以当前节点结束的新增子集的数目
  7. //当size增加时,now变为pre,并通过pre推出新的now


  8. int GetSubArrCount(vector<int> v) {
  9.         vector<int> pre(v.size()+1, 0);
  10.         pre[0] = 1;              //当子集的size为0时,只有1个子集,空集
  11.         int sum = 0;         
  12.         for (int i = 0; i <= v.size(); ++i) {
  13.                 vector<int> now(v.size() - i, 0);
  14.                 for (int j = 0; j < pre.size()-1; ++j) {  //遍历pre的元素,当元素不为0时,考虑此元素与之后的每一个不重复的元素都能构成新的不重复子集
  15.                         if (pre[j] == 0) continue;
  16.                         unordered_map<int, bool> map;
  17.                         for (int k = 0; k < pre.size()-1 - j; ++k) {
  18.                                 int a = v[i + j + k];
  19.                                 if (map[a] == false) {
  20.                                         map[a] = true;
  21.                                         now[j + k] += pre[j];
  22.                                         sum += pre[j];
  23.                                 }
  24.                         }
  25.                 }
  26.                 pre = move(now);
  27.         }
  28.         return sum;
  29. }
  30. int main() {
  31.         vector<int> v = { 1,3,2,5,3,1,4,2,5};
  32.         int i = GetSubArrCount(v);
  33.         cout << i;
  34.         system("pause");
  35. }
复制代码

评分

参与人数 1荣誉 +5 鱼币 +5 贡献 +3 收起 理由
RIXO + 5 + 5 + 3 非常好,谢了!

查看全部评分

小甲鱼最新课程 -> https://ilovefishc.com
回复

使用道具 举报

发表于 2019-4-16 13:09:20 From FishC Mobile | 显示全部楼层
本帖最后由 Croper 于 2019-4-16 13:34 编辑

如果没有不重复的要求德话直接套公式n*(n+1)/2就好了啊

//====================================分割线================================
上电脑端,看了一下,你的要求好像是要求子序列不重复且子序列是非连续子序列

首先提供一个使用stl的办法
  1. #include <vector>
  2. #include <set>
  3. #include <iostream>

  4. using namespace std;
  5. //这种方法的思路相当直接:求出所有子序列,加入set,set的大小就是不重复子序列的数量
  6. //但是效率可能稍低
  7. int GetSubArrCount(vector<int> v) {
  8.         set<vector<int>> SubArrSet;
  9.         int N = 1 << v.size();
  10.         for (int i = 1; i < N; ++i) {
  11.                 int a = i;
  12.                 vector<int> SubArr;
  13.                 for (int j = 0; a != 0; j++, a >>= 1) {
  14.                         if ((a & 1) == 1) {
  15.                                 SubArr.push_back(v[j]);
  16.                         }
  17.                 }
  18.                 SubArrSet.insert(SubArr);
  19.         }
  20.         return SubArrSet.size();
  21. }

  22. int main() {
  23.         vector<int> v = { 1,2,1};
  24.         int i = GetSubArrCount(v);
  25.         cout << i;
  26.         system("pause");
  27. }
复制代码
小甲鱼最新课程 -> https://ilovefishc.com
回复

使用道具 举报

发表于 2019-4-16 13:42:37 | 显示全部楼层
如果下午六点前没人给你更好的代码 我就给出我的思路 挺好的 差实现了
小甲鱼最新课程 -> https://ilovefishc.com
回复

使用道具 举报

 楼主| 发表于 2019-4-17 21:41:12 | 显示全部楼层
micolar 发表于 2019-4-16 13:42
如果下午六点前没人给你更好的代码 我就给出我的思路 挺好的 差实现了

呃,你还回复不,不回复我明天可就设他为最佳答案了
小甲鱼最新课程 -> https://ilovefishc.com
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|手机版|Archiver|鱼C工作室 ( 粤ICP备18085999号-1 | 粤公网安备 44051102000585号)

GMT+8, 2025-7-6 12:48

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

快速回复 返回顶部 返回列表