0 目录
242 有效的字母异位词
349 两个数组的交集(重复/无重复)
56 合并空间
75 颜色分类
242 有效的字母异位词
方法一:sort函数排序
思路:将s和t重新排列,如果t是s变位词,排序后将产生两个相同的字符串。
class Solution {
public:
bool isAnagram(string s, string t) {
int len1=s.size();
int len2=t.size();
if(len1==len2){
sort(s.begin(),s.end());
sort(t.begin(),t.end());
for(int i=0;i<len1;i++){
if(s[i]!=t[i]){
return false;
break;
}
}
return true;
}
else
return false;
}
};
复杂度分析:
- 时间复杂度:O(nlogn), 排序成本,但比较成本只有O(n)
- 空间复杂度:O(1),
方法二:哈希表
思路:小写字母共26个,用一个简单的 26 位计数器表统计每个字母个数。
class Solution {
public:
bool isAnagram(string s, string t) {
if(s.size()!=t.size())
return false;
// 创建两个26位计数器数组
int arr1[26]={0};// 数组类型为int , 表示距离a 1 2 3
int arr2[26]={0};// 注意只有与默认初始化相同才能用{0},否则{1}表示第一个为1,其余的为默认0.
for(int i=0;i<s.size();i++){
arr1[s[i]-'a']++;
arr2[t[i]-'a']++;
}
// 判别是否相同
for(int i=0;i<26;i++){
if(arr1[i]!=arr2[i])
return false;
}
return true;
}
};
复杂度分析 :
- 时间复杂度:O(n),访问计数器。
- 空间复杂度:O(1),尽管使用了额外空间,是常数空间。
349 两个数组的交集 (无重复)
法一:unordered_set
思路:使用无序set把重复数字删掉,再遍历用find()查看是否有重复。
class Solution {
public:
vector<int> intersection(vector<int>& nums1, vector<int>& nums2) {
//使用unordered_set去掉重复元素
unordered_set<int> s1;
for(int a:nums1)
s1.insert(a);
unordered_set<int> s2;
for(int b:nums2)
s2.insert(b);
// 再查看是否有交集
vector<int> res;
for(int e:s1){
if(s2.find(e)!=s2.end())
res.push_back(e);
}
return res;
}
};
复杂度分析 :
- 时间复杂度:O(n),比较时
- 空间复杂度:O(n),哈希表
350 两个数组的交集 (有重复)
法一:暴力遍历
class Solution {
public:
vector<int> intersect(vector<int>& nums1, vector<int>& nums2) {
vector<int> res;
for(auto it1=nums1.begin();it1!=nums1.end();it1++)
for(auto it2=nums2.begin();it2!=nums2.end();it2++){
if(*it1==*it2){
res.push_back(*it1);
*it2=-100000;
break;
}
}
return res;
}
};
复杂度分析 :
- 时间复杂度:O(n^2)
- 空间复杂度:O(1)
法二:迭代器
class Solution {
public:
vector<int> intersect(vector<int>& nums1, vector<int>& nums2) {
vector<int> res;
// 迭代器
for(int i=0;i<nums1.size();i++){
vector<int>::iterator it=find(nums2.begin(),nums2.end(),nums1[i]);//find返回迭代器vector<int>::iterator,用auto耗时
if(it!=nums2.end()){//找到了
res.push_back(*it);
nums2.erase(it);//避免第二次重复,要删除
}
}
return res;
}
};
复杂度分析 :
- 时间复杂度:O(n)
- 空间复杂度:O(1)
法三:哈希表map
思路:用map<int,int>存放元素和出现次数,存放其中一个数组。另一个数组在map中查找键值,若查找到,则检验出现此时是否为0,不为0,则插入结果,且改变出现次数
class Solution {
public:
vector<int> intersect(vector<int>& nums1, vector<int>& nums2) {
// 用一个初始化map
map<int,int> a;
for(int i=0;i<nums2.size();i++){
if(a.count(nums2[i]))// 有出现过
a[nums2[i]]++;// 数值加一
else
a.insert(pair<int,int>(nums2[i],1));// 初始化用insert插入pair对
}
// 在第二个里面查找比对
vector<int> res;
for(int i=0;i<nums1.size();i++){
if(a[nums1[i]]!=0){//还有存留
res.push_back(nums1[i]);
a[nums1[i]]--;//数值减一
}
}
return res;
}
};
复杂度分析 :
- 时间复杂度:O(n)
- 空间复杂度:O(n)
56 合并空间
思路:
首先题目并没有说明数组是排序的,所以我们第一步进行排序,根据数组第一位升序排序,一旦第一位相等则按第二位降序排序。
第二,由于在原数组进行更改的话需要花费太多时间在删除元素和更改元素上,所以我们声明一个二维数组存放结果,一个一维数组暂时存放要插入的数据。
由于是排序过的,所以我们在判断的时候先判断区间下边界是否大于等于下个区间的上边界,若是则可以判断出此时两区间存在重复,反之两区间不重复;继续判断区间的下边界是否小于下个区间的下边界,若是则说明两区间存在交叉,反之说明是区间包含。
class Solution {
public:
static bool cmp(const vector<int>&a,const vector<int>&b )
{
if(a[0]==b[0])
return a[1]>b[1];
return a[0]<b[0];
}
vector<vector<int>> merge(vector<vector<int>>& intervals) {
if(intervals.empty()) return intervals;
// 先排序
sort(intervals.begin(),intervals.end(),cmp);
// 初始化
vector<vector<int>> res;
vector<int> temp;
temp.push_back(intervals[0][0]);
temp.push_back(intervals[0][1]);
res.push_back(temp);
// 循环遍历剩下的和已经放进res的比较
int count=0;
for(int i=1;i<intervals.size();i++)
{
if(res[count][1]>=intervals[i][0])
{
if(res[count][1]<=intervals[i][1])
{
res[count][1]=intervals[i][1];
}
}
else
{
count++;
temp[0]=intervals[i][0];
temp[1]=intervals[i][1];
res.push_back(temp);
}
}
return res;
}
};
复杂度分析 :
- 时间复杂度:O(nlogn)
- 空间复杂度:O(n^2)
75 颜色分类
思路:我们用三个指针(p1, p2 和curr)来分别追踪0的最右边界,2的最左边界和当前考虑的元素.
class Solution {
public:
void sortColors(vector<int>& nums) {
int p1=0,curr=0,p2=nums.size()-1;
while(curr<=p2){
if(nums[curr]==0){
swap(nums[curr],nums[p1]);
curr++;// 左边换过来的一定是0了,无须再验
p1++;
}
else if(nums[curr]==2){
swap(nums[curr],nums[p2]);
p2--;
}
else// 是1
curr++;
}
}
};
复杂度分析
时间复杂度 :由于对长度 N的数组进行了一次遍历,时间复杂度为O(N)。
空间复杂度 :由于只使用了常数空间,空间复杂度为O(1) 。