原文链接;【LeetCode学习计划】《数据结构入门-C++》第2天 数组_Wang_Xin_Ling的博客-CSDN博客
目录
1. 两数之和LeetCode: 1. 两数之和
方法一:暴力破解
方法2:哈希表方法1中时间复杂度较高的原因是内层寻找target-x的复杂度较高,
主要是思路:
88. 合并两个有序数组LeetCode: 88. 合并两个有序数组
方法1:合并后排序
方法2:双指针
方法3:逆向双指针
1. 两数之和
LeetCode: 1. 两数之和
题目:
给定一个整数数组 nums 和一个整数目标值 target,请你在该数组中找出 和为目标值 target 的那 两个 整数,并返回它们的数组下标。
你可以假设每种输入只会对应一个答案。但是,数组中同一个元素在答案里不能重复出现。
你可以按任意顺序返回答案。
思路: 我们先找到一个数,我们设为x,则另外的一个数就是target - x
于是我们可以使用两重循环,外层确定一个x,内层寻找target-x
方法一:暴力破解
class Solution {
public:
vector twoSum(vector& nums, int target) {
const int n = nums.size();
for(int left = 0;left < n;left++)
{
for(int right = left +1;right
方法2:哈希表
方法1中时间复杂度较高的原因是内层寻找target-x的复杂度较高,
而使用哈希表,可以使查找target-x的时间复杂度从O ( n ) ——> O(1)。
主要是思路:
对于每一个x,先查找target-x是否在哈希表中,若在则返回答案。然后把x插入到哈希表中。
解析
1.什么是vector?
向量(Vector)是一个封装了动态大小数组的顺序容器(Sequence Container)。跟任意其它类型容器一样,它能够存放各种类型的对象。可以简单的认为,向量是一个能够存放任意类型的动态数组。
2.c++的容器——unordered_map,它是一个关联容器,内部采用的是hash表结构,拥有快速检索的功能 参考文章 STL—unordered_map 哈希表_ZS_Wang_Blogs的博客-CSDN博客
3.auto it = hashtable.find(target - nums[i]);
if (it != hashtable.end())
return {it->second, i};
hashtable[nums[i]] = i;
1)it->first和it->second相当于键和值 对应map 就是类似python中的字典
2)hashtable[nums[i]]=i相当于插入操作
3)find函数返回的是一个迭代器(就是索引)
4)it是一个指针 存了哈希表每一项的信息
5)auto it = hashtable.find(target - nums[i]); if (it != hashtable.end())
这两个组合在一起的意思是 元素如果在哈希表中
则 证明找到return 键值对 和 i(就是x的索引)
这几行代码总体意思就是找到 target - x 元素的下标
#include
#include
using std::unordered_map;
using std::vector;
class Solution
{
public:
vector twoSum(vector &nums,int target)
{
unordered_map hashtable;
for(int i = 0;i second,i};
hashtable[nums[i]] = i;
}
return {};
}
};
88. 合并两个有序数组
LeetCode: 88. 合并两个有序数组
给你两个按 非递减顺序 排列的整数数组 nums1 和 nums2,另有两个整数 m 和 n ,分别表示 nums1 和 nums2 中的元素数目。
请你 合并 nums2 到 nums1 中,使合并后的数组同样按 非递减顺序 排列。
注意:最终,合并后数组不应由函数返回,而是存储在数组 nums1 中。为了应对这种情况,nums1 的初始长度为 m + n,其中前 m 个元素表示应合并的元素,后 n 个元素为 0 ,应忽略。nums2 的长度为 n 。
方法1:合并后排序
最暴力的方法就是把nums2的所有元素先插入到nums1的后面,然后对nums1进行排序
#include
#include
using namespace std;
class Solution
{
public:
void merge(vector &num1,int m,vector &num2,int n)
{
for (int i = 0;i
方法2:双指针
题目中提到两个数组都是已排序好的,于是我们在各数组的起始项设置一个指针,这样我们就能从小至大遍历2个数组了。每次遍历,将两个指针指向的更小的那个值存入一个新数组ans。最后将整个ans复制到nums1中即可
字有点丑,博主在坚持每天练字了
#include
using namespace std;
class Solution
{
public:
void merge(vector &nums1, int m, vector &nums2, int n)
{
int p1 = 0, p2 = 0, p = 0;
int *ans = new int[m + n];
while (p1 < m && p2 < n)
{
if (nums1[p1] < nums2[p2])
{
ans[p] = nums1[p1];
p1++;
p++;
}
else
{
ans[p] = nums2[p2];
p2++;
p++;
}
}
while (p1 < m)
{
ans[p] = nums1[p1];
p1++;
p++;
}
while (p2 < n)
{
ans[p] = nums2[p2];
p2++;
p++;
}
for (int i = 0; i < m + n; i++)
{
nums1[i] = ans[i];
}
}
};
方法3:逆向双指针
方法2中需要用到中间数组的根本原因是:我们在确认nums1每个位置最终的元素时,又要保持原数组nums1不变。
而方法3的入手点在于:nums1数组的后半部分是无效值,也就是说这一部分的值是不用维护的。这样一来,我们可以在nums1和nums2数组的末项处各设置一个指针,每次将更大的元素存入nums1,这样就不会覆盖掉nums1中任何未被遍历的值,而且也省去了用于维护的中间数组。
字有点丑,博主在坚持每天练字了
#include
using namespace std;
class Solution
{
public:
void merge(vector &nums1, int m, vector &nums2, int n)
{
int p1 = m - 1, p2 = n - 1, p = m + n - 1;
while (p1 >= 0 && p2 >= 0)
{
if (nums1[p1] < nums2[p2])
{
nums1[p] = nums2[p2];
p2--;
p--;
}
else
{
nums1[p] = nums1[p1];
p1--;
p--;
}
}
while (p1 >= 0)
{
nums1[p] = nums1[p1];
p1--;
p--;
}
while (p2 >= 0)
{
nums1[p] = nums2[p2];
p2--;
p--;
}
}
};
方法2:哈希表
方法1中时间复杂度较高的原因是内层寻找target-x的复杂度较高,
而使用哈希表,可以使查找target-x的时间复杂度从O ( n ) ——> O(1)。
主要是思路:
对于每一个x,先查找target-x是否在哈希表中,若在则返回答案。然后把x插入到哈希表中。
解析
1.什么是vector?
向量(Vector)是一个封装了动态大小数组的顺序容器(Sequence Container)。跟任意其它类型容器一样,它能够存放各种类型的对象。可以简单的认为,向量是一个能够存放任意类型的动态数组。2.c++的容器——unordered_map,它是一个关联容器,内部采用的是hash表结构,拥有快速检索的功能 参考文章 STL—unordered_map 哈希表_ZS_Wang_Blogs的博客-CSDN博客
3.auto it = hashtable.find(target - nums[i]);
if (it != hashtable.end())
return {it->second, i};
hashtable[nums[i]] = i;1)it->first和it->second相当于键和值 对应map
就是类似python中的字典 2)hashtable[nums[i]]=i相当于插入操作
3)find函数返回的是一个迭代器(就是索引)
4)it是一个指针 存了哈希表每一项的信息
5)auto it = hashtable.find(target - nums[i]); if (it != hashtable.end())
这两个组合在一起的意思是 元素如果在哈希表中
则 证明找到return 键值对 和 i(就是x的索引)
这几行代码总体意思就是找到 target - x 元素的下标
#include#include using std::unordered_map; using std::vector; class Solution { public: vector twoSum(vector &nums,int target) { unordered_map hashtable; for(int i = 0;i second,i}; hashtable[nums[i]] = i; } return {}; } };
88. 合并两个有序数组
LeetCode: 88. 合并两个有序数组
给你两个按 非递减顺序 排列的整数数组 nums1 和 nums2,另有两个整数 m 和 n ,分别表示 nums1 和 nums2 中的元素数目。
请你 合并 nums2 到 nums1 中,使合并后的数组同样按 非递减顺序 排列。
注意:最终,合并后数组不应由函数返回,而是存储在数组 nums1 中。为了应对这种情况,nums1 的初始长度为 m + n,其中前 m 个元素表示应合并的元素,后 n 个元素为 0 ,应忽略。nums2 的长度为 n 。
方法1:合并后排序
最暴力的方法就是把nums2的所有元素先插入到nums1的后面,然后对nums1进行排序
#include#include using namespace std; class Solution { public: void merge(vector &num1,int m,vector &num2,int n) { for (int i = 0;i 方法2:双指针
题目中提到两个数组都是已排序好的,于是我们在各数组的起始项设置一个指针,这样我们就能从小至大遍历2个数组了。每次遍历,将两个指针指向的更小的那个值存入一个新数组ans。最后将整个ans复制到nums1中即可
字有点丑,博主在坚持每天练字了
#includeusing namespace std; class Solution { public: void merge(vector &nums1, int m, vector &nums2, int n) { int p1 = 0, p2 = 0, p = 0; int *ans = new int[m + n]; while (p1 < m && p2 < n) { if (nums1[p1] < nums2[p2]) { ans[p] = nums1[p1]; p1++; p++; } else { ans[p] = nums2[p2]; p2++; p++; } } while (p1 < m) { ans[p] = nums1[p1]; p1++; p++; } while (p2 < n) { ans[p] = nums2[p2]; p2++; p++; } for (int i = 0; i < m + n; i++) { nums1[i] = ans[i]; } } }; 方法3:逆向双指针
方法2中需要用到中间数组的根本原因是:我们在确认nums1每个位置最终的元素时,又要保持原数组nums1不变。而方法3的入手点在于:nums1数组的后半部分是无效值,也就是说这一部分的值是不用维护的。这样一来,我们可以在nums1和nums2数组的末项处各设置一个指针,每次将更大的元素存入nums1,这样就不会覆盖掉nums1中任何未被遍历的值,而且也省去了用于维护的中间数组。
字有点丑,博主在坚持每天练字了
#includeusing namespace std; class Solution { public: void merge(vector &nums1, int m, vector &nums2, int n) { int p1 = m - 1, p2 = n - 1, p = m + n - 1; while (p1 >= 0 && p2 >= 0) { if (nums1[p1] < nums2[p2]) { nums1[p] = nums2[p2]; p2--; p--; } else { nums1[p] = nums1[p1]; p1--; p--; } } while (p1 >= 0) { nums1[p] = nums1[p1]; p1--; p--; } while (p2 >= 0) { nums1[p] = nums2[p2]; p2--; p--; } } };



