文章目录

  • 前言
  • 解题过程
    • 爬楼梯的最少成本
    • 题目分析
    • DP优化
    • 利用tie进行写法优化
  • std::tuple
    • std::tuple的访问
    • std::tie函数中使用std::ignore占位
  • 总结

前言

今天主要学习一下 std::tie 函数的使用方法,之前看到 tie 函数是和 IO 绑定的,最近发现它是和 std::tuple 绑定的,查询资料后发现两个函数虽然名字相同,但是在不同的作用域下,今天学一下和 tuple 有关的这个 tie 函数,不过在学习之前先看一道小题。

解题过程

爬楼梯的最少成本

这是 LeetCode 上的一道题,题目描述如下:

数组的每个下标作为一个阶梯,第 i 个阶梯对应着一个非负数的体力花费值 cost[i](下标从 0 开始)。

每当爬上一个阶梯都要花费对应的体力值,一旦支付了相应的体力值,就可以选择向上爬一个阶梯或者爬两个阶梯。

请找出达到楼层顶部的最低花费。在开始时,你可以选择从下标为 0 或 1 的元素作为初始阶梯。

示例 1:

输入:cost = [10, 15, 20]
输出:15
解释:最低花费是从 cost[1] 开始,然后走两步即可到阶梯顶,一共花费 15 。

示例 2:

输入:cost = [1, 100, 1, 1, 1, 100, 1, 1, 100, 1]
输出:6
解释:最低花费方式是从 cost[0] 开始,逐个经过那些 1 ,跳过 cost[3] ,一共花费 6 。

提示:

2 <= cost.length <= 1000
0 <= cost[i] <= 999

题目分析

这种求解最小花费、最大方案数,最大价值的题目是典型的动态规划题目,这道题也可以使用动态规划的方式来解,既然每次可以选择爬一个或者两个阶梯,那么到达某一个阶梯的花费就等于这个阶梯的花费加上前一个阶梯花费和前两个花费的之间最小值即可,最终的结果取最后一个阶梯和倒数第二个阶梯中的最小值,代码比较简单,实现如下:

class Solution {public:int minCostClimbingStairs(vector<int>& cost) {int n = cost.size();vector<int> ans(n);ans[0] = cost[0];ans[1] = cost[1];for (int i = 2; i < n; i++) ans[i] = min(ans[i-1], ans[i-2]) + cost[i];return min(ans[n-1], ans[n-2]);}
};

DP优化

虽然使用dp数组求解起来很方便,但是从实现上可以看出,每个阶梯的花费只与它前两个阶梯的花费有关,所以使用一个长度为N的数组在空间上有些浪费,其实只要两个变量就可以了,我们用 firstsecond 两个变量分别表示某个阶梯前两个阶梯的花费,可以实现如下代码:

class Solution {public:int minCostClimbingStairs(vector<int>& cost) {int n = cost.size(), first = cost[0], second = cost[1];for (int i = 2; i < n; i++) {int temp = min(first, second) + cost[i];first = second;second = temp;}return min(first, second);}
};

利用tie进行写法优化

使用两个变量优化之后这个算法变成了 O(1) 的空间复杂度,但是在 for 循环中的写法还是有些啰嗦,其实这种写法和交换两个变量值过程非常相似,在GO语言中可以写成 a,b = b,a 来完成交换,但是在C++中这样的写法是错误的,不管是引入第三个变量,还是通过异或解决都需要写三条语句,但是这种情况在遇到 std::tie 函数之后有望得到改变,上面的写法利用 std::tie 可以改写如下:

class Solution {public:int minCostClimbingStairs(vector<int>& cost) {int n = cost.size(), first = cost[0], second = cost[1];for (int i = 2; i < n; i++) tie(first, second) = make_tuple(second, min(first, second) + cost[i]);return min(first, second);}
};

std::tuple

在学习 std::tie 的作用方式之前,先来看一下 std::tuple 是什么。如果你对这个结构有些陌生,可以先想想 std::pair 这个结构。首先 std::tuple 是一个类模板,同时他也是一个固定大小的由各种类型的值组成集合,是 std::pair 的一种泛化实现。

std::pair 中包含两个元素,而 std::tuple 可以同时包含多个元素,它拥有 struct 的表现,但是无需定义实际的 struct,在函数返回多个值时拥有良好的表现。

std::tuple的访问

  1. 利用 std::get 函数通过下标访问(C++11)
    auto t = std::make_tuple(110, "excellent", 3.14);std::cout << "(" << std::get<0>(t) << ", " << std::get<1>(t)<< ", " << std::get<2>(t) << ")" << std::endl;
  1. 利用 std::tie 函数进行参数解绑(C++11)
    auto t = std::make_tuple(110, "excellent", 3.14);int n;std::string s;float d;std::tie(n, s, d) = t;std::cout << "(" << n << ", " << s << ", " << d << ")" << std::endl;
  1. 利用 std::get 函数通过类型访问(C++14),这种使用方式如果每种类型不唯一会出现编译错误
    auto t = std::make_tuple(110, "excellent", 3.14);std::cout << "(" << std::get<int>(t) << ", " << std::get<const char*>(t)<< ", " << std::get<double>(t) << ")" << std::endl;
  1. 利用结构化绑定的方式来访问(C++17)
    auto t = std::make_tuple(110, "excellent", 3.14);auto [n, s, d] = t;std::cout << "(" << n << ", " << s << ", " << d << ")" << std::endl;

以上的几个例子的输出结果都是 (110, excellent, 3.14)

std::tie函数中使用std::ignore占位

使用 std::tie 函数来获取 std::tuple 参数时,有时不需要所有的参数,这种情况下可以使用 td::ignore 来占位,代替那些不关心的参数,比如 std::set 结构中 insert 函数的返回值。

    std::set<int> st;std::pair<std::set<int>::iterator, bool> sp1 = st.insert(4);std::cout << *sp1.first << " " << sp1.second << std::endl;std::pair<std::set<int>::iterator, bool> sp2 = st.insert(4);std::cout << *sp2.first << " " << sp2.second << std::endl;

运行结果如下:

4 1
4 0

如果我们不关心插入的元素是什么,只想知道此次插入操作是否成功,可以利用 std::tiestd::ignore 来实现:

    std::set<int> st;bool inserted = false;std::tie(std::ignore, inserted) = st.insert(4);std::cout << inserted << std::endl;std::tie(std::ignore, inserted) = st.insert(4);std::cout << inserted << std::endl;

运行结果如下:

1
0

总结

  • std::tuplestd::pair 一种更加通用的实现,std::pair 只能包含两个元素,而 std::tuple 可以包含多个任意类型的元素
  • tie 本意是系牢、约束、连接、束缚的意思,用在 std::tuple 上却是用来解绑参数的,含义恰好相反了,很有趣是不是
  • 实际上 std::tie 这个函数的作用是把一些左值绑定到 std::tuple 来达到解析参数的目的,函数作用还是 “tie”
  • std::ignore 可以用在 std::tie 函数中作为占位符,用来替代一些不关心的参数

==>> 反爬链接,请勿点击,原地爆炸,概不负责!<<==


有些事情反过来想一想,问题可能很快就解决了——记一次拼图游戏中一个对手的高谈阔论

从一个小题中的应用来体会下std::tie的便利之处相关推荐

  1. 关于阿里面试的一个小题(推荐)

    最近搜到的阿里一个面试小题要求如下: 用div+css做出如下效果: 用js做出: 当鼠标悬停在红色div上时,div放大,并且不占挤其他盒子效果如下: 代码如下 1 <!DOCTYPE htm ...

  2. Python 匿名函数lambda 相关的一个小题

    #问题:下面输出结果是多少? a=[1, 2, 3, 4, 5] # 创建列表a,并将1, 2, 3, 4, 5赋值给列表a sums = sum(map(lambda x: x + 3, a[1:: ...

  3. 关于阿里面试的的一个小题

    看到同学找到了阿里的这么一个面试题,感觉挺有趣,就做了做. 用div+css做出如下效果: 当鼠标移入带红色div上的时候,div的大小增大25%,其他的不变.如下图: 详细代码如下: <!do ...

  4. 如何在Word中的一个小方框中插入箭头

    选择 "插入"-"符号",在字体中选择 "Wingdings",向下拖动滚动条,选择þ 转载于:https://www.cnblogs.co ...

  5. 实验2.3 使用重载函数模板重新实现上小题中的函数Max1

    题目 使用重载函数模板重新可分别求取两个整数,三个整数,两个双精度数,三个双精度数的最大值 AC的C++代码如下: #include<iostream> #include<algor ...

  6. 椭圆极点极线性质_又见阿氏圆——适合作椭圆大题的小题

    如下图:过椭圆内一点作的直线交椭圆于,两点.是椭圆上相异的两点,满足分别平分,,求外接圆半径的最小值. 解:作的外角角平分线与的延长线交于,的外角平分线与的延长线交于,根据内外角平分线定理(调和点列. ...

  7. 超几何分布_概率小题——分布列专题

    本期将介绍概率小题中的最后一个考点分布列,其中包括分布列的定义.求法和性质,以及如何通过分布列求解期望和方差,以及期望和方差的性质:除此之外还涉及到部分典型分布分布列的求法已经对应期望和方差的求解公式 ...

  8. 《十六》微信小程序中的分包

    某些情况下,开发者需要将小程序划分成不同的子包,在构建时打包成不同的分包,用户在使用时按需进行加载. 在构建小程序分包项目时,构建会输出一个或多个分包.每个使用分包小程序必定含有一个主包.所谓的主包, ...

  9. Java黑皮书课后题第8章:*8.24(检验数独的解决方案)程序清单8-4通过检测棋盘上的每个数字是否是有效的,从而检验一个解决方案是否是有效的。重写该程序,通过检验是否每行、每列、每个小方盒中具有

    *8.24(检验数独的解决方案)程序清单8-4通过检测棋盘上的每个数字是否是有效的,从而检验一个解决方案是否是有效的.重写该程序 题目 题目描述 程序清单8-4 破题 代码 题目 题目描述 *8.24 ...

最新文章

  1. JAVA关于字符串字符数组处理的小题目
  2. CentOS6.5 iscsi配置
  3. mac最好用的markdown_Markdown 语法简明教程 amp; Markdown 编辑器推荐
  4. sql server 2000 删除重复数据
  5. 计算机常用端口号汇总
  6. 蓝桥杯【(经验+资源)分享】【从零备考 蓝桥杯】说说我的经历及备考经验
  7. Struts2解析FreeMarker模板中变量的顺序
  8. why do we use process keys
  9. Mac系统如何安装Eclipse并搭建Android开发环境
  10. 怎么知道王者荣耀QQ在哪个服务器有账号,怎么查看qq号玩过王者荣耀哪个区 | 手游网游页游攻略大全...
  11. 科学革命——承认自己无知的革命
  12. 小心黑客入侵,六种黑客入侵手机的常见方式
  13. Java设计模式第一章(软件设计原则)(学习笔记)
  14. 中兴程序员坠楼事件:男人四十,人生半局
  15. epub格式电子书剖析之二:OP…
  16. js获取摄像头权限实现拍照功能
  17. Qt的初学路程(一)电子时钟
  18. 过年想网购不用愁,苏宁快递小哥这个春节不打烊!
  19. html视频文件转换成视频,Amazing Video to HTML5 Converter(视频到HTML5转换器) V1.7.0 官方版...
  20. 黑马程序员-Java高新技术-反射

热门文章

  1. 『影视评论』 [电影众论]越狱中觉得比较经典的十段台词(转载)
  2. python 分词工具对比_五款中文分词工具在线PK: Jieba, SnowNLP, PkuSeg, THULAC, HanLP
  3. ClassLoader类加载浅析
  4. CAMELYON16数据集
  5. Ajax 跨域难题 - 原生 JS 和 jQuery 的实现对比
  6. mock挡板_【接口测试】16 Postman使用mock进行挡板测试(1)
  7. 献给所有喜爱篮球的人
  8. Docker网络(host、bridge、none)详细介绍
  9. 利用约束布局ConstraintLayout实现全适配九宫格
  10. setTimeStamp()与setDate()区别 如何将java中Date存入mysql中的datetime中,字符串怎么转换为日期类型