• 基础算法 - 常见算法模板题(最简洁写法)【下】


    目录

    双指针

    最长连续不重复子序列​编辑

    二进制中1的个数

    区间和

    区间合并


    双指针

    最长连续不重复子序列

     思路:

    1. 设左右指针 j,i;用 i 遍历数组,对【j,i】范围路径数值出现次数记录
    2. 若次数大于1,则将 j 向前走,直到范围中没有重复数字
    3. 对每一步记录,即比较每个范围的长度,取最大值

    1. #include
    2. using namespace std;
    3. int a[100010],s[100010];
    4. int main()
    5. {
    6. int n,j=0,res=0;
    7. cin>>n;
    8. for(int i=0;i
    9. {
    10. cin>>a[i];
    11. s[a[i]]++;
    12. while(s[a[i]]>1)
    13. {
    14. s[a[j]]--;
    15. j++;
    16. }
    17. res=max(res,i-j+1);
    18. }
    19. cout<
    20. return 0;
    21. }

    二进制中1的个数

     思路:

    位运算(& | ~ ^ >> <<)_NO.-LL的博客-CSDN博客

    利用模板

      while(b)  b=b&(b-1);  //二进制中有多少个1就循环多少次

    1. #include
    2. #include
    3. #include
    4. #include
    5. using namespace std;
    6. const int N=1e5+10;
    7. int cnt(int b)
    8. {
    9. int res=0;
    10. while(b)
    11. {
    12. b=b&(b-1);
    13. res++;
    14. }
    15. return res;
    16. }
    17. int main()
    18. {
    19. int n,b;
    20. cin>>n;
    21. for(int i=0;i
    22. {
    23. cin>>b;
    24. cout<<cnt(b)<<" ";
    25. }
    26. return 0;
    27. }

     区间和

    思路:

    1、设vector >  add 用于存储下标x 与要加的值c ,query用于记录要求和的区间【l,r】

    2、将下标与区间(x,l,r)都存入alls中,准备离散化

    3、对alls排序并去重

     alls.erase(unique(alls.begin(), alls.end()), alls.end());

    unique作用:把alls重复元素删除,返回新数组的最后一个位置

    erase作用:把后面的元素删除,只留下去重元素

     4、设计find函数查找x,并一一映射到数组a中

    5、用前缀和就是区间和

    6、通过遍历query,完成求区间[l,r]的和。

     为什么不直接用前缀和呢?

    • 因为数据为-1e9到1e9,没办法开这么大的数组,且x下标存在负值无法存储
    1. #include
    2. #include
    3. #include
    4. using namespace std;
    5. typedef pair<int, int> PII;
    6. const int N = 300010;
    7. int n, m;
    8. int a[N], s[N];
    9. vector<int> alls;
    10. vector add, query;
    11. int find(int x) //找到大于等于x的第一个值
    12. {
    13. int l = 0, r = alls.size() - 1;
    14. while (l < r)
    15. {
    16. int mid = l + r >> 1;
    17. if (alls[mid] >= x) r = mid;
    18. else l = mid + 1;
    19. }
    20. return r + 1; //让下标从1开始,方便前缀和计算
    21. }
    22. /*int find(int x)
    23. {
    24. return lower_bound(alls.begin(),alls.end(),x)-alls.begin() +1;
    25. }*/
    26. int main()
    27. {
    28. cin >> n >> m;
    29. for (int i = 0; i < n; i ++ )
    30. {
    31. int x, c;
    32. cin >> x >> c;
    33. add.push_back({x, c});
    34. alls.push_back(x);
    35. }
    36. for (int i = 0; i < m; i ++ )
    37. {
    38. int l, r;
    39. cin >> l >> r;
    40. query.push_back({l, r});
    41. alls.push_back(l);
    42. alls.push_back(r);
    43. }
    44. // 去重
    45. sort(alls.begin(), alls.end());
    46. alls.erase(unique(alls.begin(), alls.end()), alls.end());
    47. // 处理插入
    48. for (auto item : add)
    49. {
    50. int x = find(item.first);
    51. a[x] += item.second;
    52. }
    53. // 预处理前缀和
    54. for (int i = 1; i <= alls.size(); i ++ ) s[i] = s[i - 1] + a[i];
    55. // 处理询问
    56. for (auto item : query)
    57. {
    58. int l = find(item.first), r = find(item.second);
    59. cout << s[r] - s[l - 1] << endl;
    60. }
    61. return 0;
    62. }

    区间合并

     

    思路:

    1. 记录区间左端点st与右端点ed,将区间按左端点排序
    2. 因为左端点有序,只需要判断该区间左端点与前一个区间右端位置,即可确定是否合并
    1. #include
    2. #include
    3. #include
    4. using namespace std;
    5. typedef pair<int, int> PII;
    6. void merge(vector &segs)
    7. {
    8. vector res;
    9. sort(segs.begin(), segs.end()); //将左边界排序
    10. int st = -2e9, ed = -2e9;
    11. for (auto seg : segs)
    12. if (ed < seg.first) //不重叠,取新区间
    13. {
    14. if (st != -2e9) res.push_back({st, ed}); //不是第一次,插入新区间
    15. st = seg.first, ed = seg.second;
    16. }
    17. else ed = max(ed, seg.second); //有重叠,取交集
    18. if (st != -2e9) res.push_back({st, ed}); //循环结束,对最后一个区间插入
    19. segs = res;
    20. }
    21. int main()
    22. {
    23. int n;
    24. scanf("%d", &n);
    25. vector segs;
    26. for (int i = 0; i < n; i ++ )
    27. {
    28. int l, r;
    29. scanf("%d%d", &l, &r);
    30. segs.push_back({l, r});
    31. }
    32. merge(segs);
    33. cout << segs.size() << endl;
    34. return 0;
    35. }

  • 相关阅读:
    远程服务器Ubuntu 18.04安装VNC远程桌面
    肝了一周的八万字Redis实战篇
    阿里P8大牛发布《亿级流量并发手册》GitHub下载榜飙升至第一
    GitHub配置SSH Keys步骤
    基于html5开发的Win12网页版,抢先体验
    欧科云链:成本与规模之辨——合规科技如何赋能香港Web3生态?
    Python基础——分支与循环
    Python 鼠标模拟
    iOS 提高Xcode运行速度
    【dbeaver】win环境的kerberos认证和Clouders集群中Kerberos认证使用Dbeaver连接Hive和Phoenix
  • 原文地址:https://blog.csdn.net/qq_61386381/article/details/126494394