LeetCode题目练习-Map&Set

有效的字母异位词

Given two strings s and t , write a function to determine if t is an
anagram of s.

Example 1:

Input: s = “anagram”, t = “nagaram” Output: true Example 2:

Input: s = “rat”, t = “car” Output: false

STL 容器比较:

模板 key 排序
set 不允许重复 自动排序
map 不允许重复 自动排序
multimap 允许重复 自动排序
unordered_map 不允许重复 无序
unordered_multimap 允许重复 无序

总结:set和map都是不允许重复自动排序的,加multi表示允许重复,加unordered表示无序。
unordered_map:

在cplusplus的解释:

无序映射是关联容器,用于存储由键值和映射值组合而成的元素,并允许基于键快速检索各个元素。

在unordered_map中,键值通常用于唯一标识元素,而映射值是与该键关联的内容的对象。键和映射值的类型可能不同。

在内部,unordered_map中的元素没有按照它们的键值或映射值的任何顺序排序,而是根据它们的散列值组织成桶以允许通过它们的键值直接快速访问单个元素(具有常数平均时间复杂度)。

unordered_map容器比映射容器更快地通过它们的键来访问各个元素,尽管它们通过其元素的子集进行范围迭代通常效率较低。

无序映射实现直接访问操作符(operator []),该操作符允许使用其键值作为参数直接访问映射值。

容器中的迭代器至少是前向迭代器。

关键词:无序的 快速的检索 达到的是更快的访问 但是子集的范围迭代效率低

在这里插入图片描述

//时间复杂度 N
class Solution {
    unordered_map<char,int> counts;
    //对每个字母出现次数计数。如counts['a']=3表示a出现了3次
public:
    bool isAnagram(string s, string t) {
        if(s.length() != t.length()) return false;
        for(int i = 0;i < s.length();i++){
            counts[s[i]]++;//串1中的字母出现时加一
            counts[t[i]]--;//串2中的字母出现时减一  
        }
        //如果串1和串2字母全相同,counts中的计数应为0
        for(auto count:counts)
            if(count.second) return false;
        return true;
    }
};
//另有将两个字符串数组排序后再比较的算法,Nlog(N)(快排)

两数之和

Given an array of integers, return indices of the two numbers such
that they add up to a specific target.

You may assume that each input would have exactly one solution, and
you may not use the same element twice.

Example:

Given nums = [2, 7, 11, 15], target = 9,

Because nums[0] + nums[1] = 2 + 7 = 9, return [0, 1].

来源:力扣(LeetCode) 链接:https://leetcode-cn.com/problems/two-sum
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

  • 算法一:暴力法 O(n2)
  • 算法二:set记录
    这道题有个巨坑,就是C++的set是自动排序的。我一开始用set,放入3,2,4后,再找2的时候,返回的下标是1,而答案应该是2,也就是set给我排序了,下标变了。花了好久时间想为什么返回下标是1。。所以改用vector解决问题。还有个坑,distance函数我不知道,为什么C++find不能直接返回下标,要返回迭代器,还得distance函数找距离。。
class Solution {
    vector<int> record;
    //set自动排序 不能用set做本题,只能用map/vector
    vector<int> res;
public:
    vector<int> twoSum(vector<int>& nums, int target) {
        for(int i = 0;i < nums.size();i++){
            //vector的find方法要用stl的,它没有自己的
            auto p = find(record.begin(),record.end(),target - nums[i]);
            if( p == record.end()){
                record.push_back(nums[i]);
            }else{
                res.push_back(i);
                res.push_back(distance(record.begin(),p));
                break;//找到即可返回
            }
        }
       return res;
    }
};

算法三:map
在算法二我们知道set是一维的,由下标确定值。而map是二维的,可以存元素以及下标,就这样省去了找下标的时间。

class Solution {
    unordered_map<int,int> record;
    vector<int> res;
public:
    vector<int> twoSum(vector<int>& nums, int target) {
        for(int i=0;i<nums.size();i++){
            int tmp=target-nums[i];
            if(record.find(tmp)==record.end()){
                record[nums[i]]=i;
            }else
                res.push_back(i);
                res.push_back(record[tmp]);
                //无须distance函数找下标
                break;
        }
        return res;
    }
};

算法三只是换成map,时间变为12ms,而算法二是56ms,(消耗内存都差不多),时间复杂度相同,为什么时间上差这么多?可能是distance函数慢了。

三数之和

  • 算法一:暴力O(n3)
  • 算法二:两层循环,在循环内部找target-a-b,找到了就结束,没找到就把a和b插入set中,O(n2),空间O(n)
  • 算法三:先排序(快排nlogn),b和c作为双指针,a+b+c值大于0,说明大了,左移c;小于0,说明小了右移b。时间O(n2),空间无。
发布了24 篇原创文章 · 获赞 12 · 访问量 1万+

猜你喜欢

转载自blog.csdn.net/Protocols7/article/details/103870916