题号1. 两数之和:

给定一个整数数组 nums 和一个目标值 target,请你在该数组中找出和为目标值的那 两个 整数,并返回他们的数组下标。

你可以假设每种输入只会对应一个答案。但是,你不能重复利用这个数组中同样的元素。

示例:

给定 nums = [2, 7, 11, 15], target = 9

因为 nums[0] + nums[1] = 2 + 7 = 9

所以返回 [0, 1]

才拿到这道题时,第一个反应是遍历每个元素 x,并查找是否存在一个值与 target−x 相等的目标元素的暴力解法,时间复杂度为O(n²),C++实现如下:

class Solution {
public:vector<int> twoSum(vector<int>& nums, int target) {vector<int> ret;for (int i = 0; i < nums.size(); i++){for(int j = i + 1; j < nums.size(); j++){if(nums[i] == target - nums[j]){ret.push_back(i);ret.push_back(j);return ret;}                }}ret.push_back(-1);ret.push_back(-1);return ret;}
};

系统耗时显示是164ms, 对于每个元素,我们试图通过遍历数组的其余部分来寻找它所对应的目标元素,这将耗费 O(n) 的时间。因此时间复杂度为 O(n^2),空间复杂度为O(1)。

为了对运行时间复杂度进行优化,我们需要一种更有效的方法来检查数组中是否存在目标元素。如果存在,我们需要找出它的索引。保持数组中的每个元素与其索引相互对应的最好方法是什么?哈希表。

class Solution {
public:vector<int> twoSum(vector<int>& nums, int target){unordered_map<int, int> hm1;for (int i = 0; i < nums.size(); ++i) {int complement = target - nums[i];if(hm1.find(complement) != hm1.end()){return vector<int>{hm1.find(complement)->second, i};}hm1[nums[i]] = i;}return vector<int>{-1, -1};}
};

时间立马缩减到了8ms,性能的提升是立竿见影的,但是看了标准答案,看到有位大神居然将耗时缩减到了4ms,这里附上他的解法:

static const auto io_sync_off = []()
{// turn off syncstd::ios::sync_with_stdio(false);// untie in/out streamsstd::cin.tie(nullptr);return nullptr;
}();class Solution {
public:vector<int> twoSum(vector<int>& nums, int target){map<int, int> hm1;for (int i = 0; i < nums.size(); ++i) {int complement = target - nums[i];if(hm1.find(complement) != hm1.end()){return vector<int>{hm1.find(complement)->second, i};}hm1[nums[i]] = i;}return vector<int>{-1, -1};}
};

看完特地查了下开头的函数,详细的解释在下面:https://blog.csdn.net/qq_32320399/article/details/81518476

https://blog.csdn.net/YinJianxiang/article/details/76436089

在ACM里,经常出现数据集超大造成 cin TLE的情况。这时候大部分人(包括原来我也是)认为这是cin的效率不及scanf的错,甚至还上升到C语言和C++语言的执行效率层面的无聊争论。其实像上文所说,这只是C++为了兼容而采取的保守措施。我们可以在IO之前将stdio解除绑定,这样做了之后要注意不要同时混用cout和printf之类

在默认的情况下cin绑定的是cout,每次执行 << 操作符的时候都要调用flush,这样会增加IO负担。可以通过tie(0)(0表示NULL)来解除cin与cout的绑定,进一步加快执行效率。


题号4. 寻找两个有序数组的中位数:

给定两个大小为 m 和 n 的有序数组 nums1 和 nums2

请你找出这两个有序数组的中位数,并且要求算法的时间复杂度为 O(log(m + n))。

你可以假设 nums1 和 nums2 不会同时为空。

示例 1:

nums1 = [1, 3]
nums2 = [2]则中位数是 2.0

示例 2:

nums1 = [1, 2]
nums2 = [3, 4]则中位数是 (2 + 3)/2 = 2.5

我的思路是类似二路归并排序,但是不需要新的数组来存放两个数组的数据,也不需要将所有数据全部排序,只需要取到中间两个数。首先计算出总个数,然后求出中间两个数的下标 m 和 n ,定义两个指针,分别从两个数组的左边开始向后推进,知道遍历到第 m 个和第 n 个,求出两数的平均数并返回。当然这里同样解除了 IO 的同步用于提升性能。

double findMedianSortedArrays(vector<int>& nums1, vector<int>& nums2)
{int size = nums1.size() + nums2.size();int m = 0, n = 0;// 判断中位数是两数平均值还是单个值if (size % 2 == 1) // 总个数为基数则为中间值{n = size / 2;m = n;}else                // 偶数则为中间俩个数的平均值{n = size / 2;m = n - 1;}double midData = 0;int leftPoint  = 0;int rightPoint = 0;// 获取中位数for (int i = 0; i <= n; ++i){// 对数组进行判断是否越界if ( leftPoint >= nums1.size() ) // 即将进行的操作下标将越界{if (midData == 0)midData = ( (double)( nums2[m - leftPoint] + nums2[n - leftPoint] ) ) / 2;elsemidData = ( midData + nums2[n - leftPoint] ) / 2;return midData;}if ( rightPoint >= nums2.size() ) // 即将进行的操作下标将越界{if (midData == 0)midData = ( (double)( nums1[m - rightPoint] + nums1[n - rightPoint] ) ) / 2;elsemidData = ( midData + nums1[n - rightPoint] ) / 2;return midData;}// 向后推进if (nums1[leftPoint] <= nums2[rightPoint]){if (i == m)midData = (double)nums1[leftPoint];if (i == n){midData = ( midData + nums1[leftPoint] ) / 2;return midData;}leftPoint++;} else{if (i == m)midData = (double)nums2[rightPoint];if (i == n){midData = ( midData + nums2[rightPoint] ) / 2;return midData;}rightPoint++;}}return midData;
}

这里出现了一个很奇怪的事情,我的方法在leetcode上显示的时间耗时是32ms,我采用16ms的方法,提交之后还是显示的32ms,于是我在自己电脑上写了测试用例计算耗时:

#include <iostream>
#include <windows.h>
#include <vector>
#include <unordered_map>using namespace std;// 关闭 IO 同步
static const auto io_sync_off = []()
{// turn off syncstd::ios::sync_with_stdio(false);// untie in/out streamsstd::cin.tie(nullptr);return nullptr;
}();double findMedianSortedArrays(vector<int>& nums1, vector<int>& nums2)
{int size = 0;if(nums1.size() != 0 || nums2.size() != 0){size = nums1.size() + nums2.size();}else{return false;}int m = 0, n = 0;// 判断中位数是两数平均值还是单个值if (size % 2 == 1) // 总个数为基数则为中间值{n = size / 2;m = n;}else                // 偶数则为中间俩个数的平均值{n = size / 2;m = n - 1;}double midData = 0;int leftPoint  = 0;int rightPoint = 0;// 获取中位数for (int i = 0; i <= n; ++i){// 对数组进行判断是否越界if ( leftPoint >= nums1.size() ) // 即将进行的操作下标将越界{if (midData == 0)midData = ( (double)( nums2[m - leftPoint] + nums2[n - leftPoint] ) ) / 2;elsemidData = ( midData + nums2[n - leftPoint] ) / 2;return midData;}if ( rightPoint >= nums2.size() ) // 即将进行的操作下标将越界{if (midData == 0)midData = ( (double)( nums1[m - rightPoint] + nums1[n - rightPoint] ) ) / 2;elsemidData = ( midData + nums1[n - rightPoint] ) / 2;return midData;}// 向后推进if (nums1[leftPoint] <= nums2[rightPoint]){if (i == m)midData = (double)nums1[leftPoint];if (i == n){midData = ( midData + nums1[leftPoint] ) / 2;return midData;}leftPoint++;} else{if (i == m)midData = (double)nums2[rightPoint];if (i == n){midData = ( midData + nums2[rightPoint] ) / 2;return midData;}rightPoint++;}}return midData;
}// 性能最优解法
int findKth(vector<int> nums1, vector<int> nums2, int k)
{if (nums1.empty()) return nums2[k - 1];if (nums2.empty()) return nums1[k - 1];if (k == 1) return min(nums1[0], nums2[0]);int i = min((int)nums1.size(), k / 2), j = min((int)nums2.size(), k / 2);if (nums1[i - 1] > nums2[j - 1]) {return findKth(nums1, vector<int>(nums2.begin() + j, nums2.end()), k - j);} else {return findKth(vector<int>(nums1.begin() + i, nums1.end()), nums2, k - i);}return 0;
}double findMedianSortedArrays2(vector<int>& nums1, vector<int>& nums2)
{int m = nums1.size(), n = nums2.size();return (findKth(nums1, nums2, (m + n + 1) / 2) + findKth(nums1, nums2, (m + n + 2) / 2)) / 2.0;
}int main()
{struct timespec startTime,endTime;// 题号 4 测试用例
#if 1clock_gettime(CLOCK_MONOTONIC, &startTime);vector<int> vector1;vector<int> vector2;vector1.push_back(1);vector1.push_back(2);vector2.push_back(4);vector2.push_back(6);clock_gettime(CLOCK_MONOTONIC, &endTime);cout << "pushIn vector time cost :" << endTime.tv_nsec - startTime.tv_nsec << " ns" << endl;// my methodclock_gettime(CLOCK_MONOTONIC, &startTime);for (int i = 0; i < 10; ++i)findMedianSortedArrays(vector1,vector2);clock_gettime(CLOCK_MONOTONIC, &endTime);cout << "my   function time cost :" << endTime.tv_nsec - startTime.tv_nsec << "ns" << endl;// 最佳方法clock_gettime(CLOCK_MONOTONIC, &startTime);for (int i = 0; i < 10; ++i)findMedianSortedArrays2(vector1,vector2);clock_gettime(CLOCK_MONOTONIC, &endTime);cout << "best function time cost :" << endTime.tv_nsec - startTime.tv_nsec << "ns" << endl;
#endifreturn 0;
}

我的电脑上函数运行10次耗时如图所示。

leetcode练习——数组篇(1)(std::ios::sync_with_stdio(false);std::cin.tie(nullptr);)相关推荐

  1. 【C++】ios::sync_with_stdio(false) 与 cin.tie(nullptr) 加速 IO

    目录&索引 一.前言 题目 二.ios::sync_with_stdio(false) 三.cin.tie(nullptr) 四.小结 一.前言 之前写题遇到大数据量(cin.cout 数据量 ...

  2. 解析 static auto x = []() { std::ios::sync_with_stdio(false);std::cin.tie(nullptr);return 0;}()

    前言 这两天在LeetCode上刷题的时候看见有好几个速度排名第一的代码中都有一段类似的代码,如下: static const auto io_sync_off = []() {// turn off ...

  3. 关于ios::sync_with_stdio(false);和 cin.tie(0)加速c++输入输出流

    原文地址:http://www.hankcs.com/program/cpp/cin-tie-with-sync_with_stdio-acceleration-input-and-output.ht ...

  4. C++输入输出流加速器,关闭同步流,ios::sync_with_stdio(false)和 cin.tie(0)

    leetcode练习时,总会发现运行时间短的代码都会有类似: static int x=[](){std::ios::sync_with_stdio(false);cin.tie(NULL);retu ...

  5. std::ios::sync_with_stdio(false)的运用

    c++中cin,cout效率比较低,是因为先把要输出的东西存入缓冲区与C语言中的stdio同步后,再输出,导致效率降低,而这段语句的作用是取消缓冲区同步,直接使用,由此可节省时间,使效率与scanf与 ...

  6. 关于std::ios::sync_with_stdio(false)

    std::ios::sync_with_stdio(false); 很多C++的初学者可能会被这个问题困扰,经常出现程序无故超时,最终发现问题处在cin和cout上,(甚至有些老oier也会被这个问题 ...

  7. C++ 里利用 std::ios::sync_with_stdio(false) 解决TLE问题

    2018-1-23 关于用C++里面的cin读取数据,我们都知道它的速度相对于C里面的scanf是比较慢的... 首先,我随机生成了10000000个整数 #include<stdio.h> ...

  8. std::ios::sync_with_stdio(false);

    这句语句是用来取消cin的同步,什么叫同步呢?就是iostream的缓冲跟stdio的同步.如果你已经在头文件上用了using namespace std;那么就可以去掉前面的std::了.取消后就c ...

  9. 拾趣——ios::sync_with_stdio(false)详解(提高代码运算速度)

    本篇文章核心意思:在编程时cin(cout)比scanf(printf)慢,在代码里加上ios::sync_with_stdio(false) 这个语句后,cin(cout)速度就会变得和scanf( ...

最新文章

  1. 在线作图|在线做UMAP降维分析
  2. 如何同时展现不同粒度的度量
  3. getResources().getIdentifier(textView01, id, cn.xxx.xxx);
  4. 远程连接身份验证错误,又找不到加密Oracle修正
  5. Android .mk文件语法解析
  6. HDFS 原理、架构与特性介绍--转载
  7. 终端界面如何改成彩色的
  8. 『算法』读书笔记 1.4算法分析 Part1
  9. [cocos2d-x]屏幕自适应解决的方法
  10. MySQL视图,触发器,事务,存储过程,函数
  11. IDEA 2017.3.3 Mybatis Plugin 3.154 安装和破解方法(Windows系统)
  12. Verilog学习——T触发器
  13. Chess.com:象棋社区网站每月访问量达 2.8 亿,年收入在 5000 万至 1 亿之间
  14. Python + PIL 处理支付宝AR红包
  15. SQL注入漏洞(postgresql注入)
  16. html给标题设置背景,怎么在html中设置一级标题背景
  17. 纵断面图标注栏数据复制
  18. 第二次实验报告:使用Packet Tracer分析应用层协议
  19. 利用ESP8266Audio库实现ESP8266语音播报功能
  20. 9、向导制作LQFP48L表贴封装

热门文章

  1. 镇江 linux技术支持,东云镇江服务器
  2. mysql 递归实现树形_Mysql实现树形递归查询
  3. php开发地图导航,php 实现百度地图(很详细出来的地图)
  4. c++查询当前文件夹下文件数目_python3自动化小工具--删除某个文件夹xx后缀文件...
  5. 食饵捕食者模matlab,几类食饵-捕食者模型的定性分析和数值模拟
  6. 【算法系列之十四】最大子序和
  7. 基础的shell编程问题(一)
  8. 剑指offer:12-17记录
  9. leetcode1 两数之和
  10. 根据数组建立平衡二叉搜索树