算法(十五)数组之哈希表

leetcode

[hot] 1. 两数之和

题目

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

你可以假设每种输入只会对应一个答案。但是,数组中同一个元素不能使用两遍。你可以按任意顺序返回答案。

题解

map解决问题,一边遍历数组一边寻找target-nums[i]是否存在于map中,这样用O(n)的时间就能够找到目标pair,示例代码如下:

class Solution {
public:
    vector<int> twoSum(vector<int>& nums, int target) {
        int length = nums.size();
        map<int, int> m;

        m[nums[0]] = 0;
        
        for (int i = 1; i < length; ++i) {
            if (m.count(target - nums[i]) > 0) {
                return {m[target - nums[i]], i};
            }
            m[nums[i]] = i;
        }

        return vector<int>();
    }
};

复杂度

时间复杂度: O ( n ) O(n) O(n)
空间复杂度: O ( n ) O(n) O(n),map的辅助空间

[hot] 49. 字母异位词分组

题目

给你一个字符串数组,请你将 字母异位词 组合在一起。可以按任意顺序返回结果列表。字母异位词 是由重新排列源单词的所有字母得到的一个新单词。

示例 1:
输入: strs = ["eat", "tea", "tan", "ate", "nat", "bat"]
输出: [["bat"],["nat","tan"],["ate","eat","tea"]]

示例 2:
输入: strs = [""]
输出: [[""]]

示例 3:
输入: strs = ["a"]
输出: [["a"]]

题解

通过map映射进行求解,示例代码如下所示:

class Solution {
public:
    vector<vector<string>> groupAnagrams(vector<string>& strs) {
        vector<vector<string>> res;
        map<string, vector<string>> m;
        for (const auto& str: strs) {
            string s = string(26, '0');
            for (const auto& c: str) {
                ++s[c - 'a'];
            }
            m[s].emplace_back(str);
        }

        for (const auto& elem: m) {
            res.emplace_back(elem.second);
        }

        return res;
    }
};

复杂度

时间复杂度: O ( n ) O(n) O(n)
空间复杂度: O ( n ) O(n) O(n)

[hot] 347. 前 K 个高频元素

题目

给定一个非空的整数数组,返回其中出现频率前 k 高的元素。

示例 1:
输入: nums = [1,1,1,2,2,3], k = 2
输出: [1,2]

示例 2:
输入: nums = [1], k = 1
输出: [1]

题解

桶排序解决问题,示例代码如下所示:

class Solution {
public:
    vector<int> topKFrequent(vector<int>& nums, int k) {
        map<int, int> m;
        for (auto& num: nums) {
            if (m.count(num) > 0) {
                ++m[num];
            } else {
                m[num] = 1;
            }
        }

        int length = nums.size();
        vector<vector<int>> ctnr(length + 1, vector<int>());
        for (auto& elem: m) {
            auto& key = elem.first;
            auto& value = elem.second;
            ctnr[value].emplace_back(key);
        }

        vector<int> res;
        for (int i = length; res.size() < k && i >= 0; --i) {
            for (int j = 0; res.size() < k && j < ctnr[i].size(); ++j) {
                res.emplace_back(ctnr[i][j]);
            }
        } 

        return res;
    }
};

复杂度

时间复杂度: O ( n ) O(n) O(n)
空间复杂度: O ( n ) O(n) O(n)

763. 划分字母区间

题目

给你一个字符串 s 。我们要把这个字符串划分为尽可能多的片段,同一字母最多出现在一个片段中。注意,划分结果需要满足:将所有划分结果按顺序连接,得到的字符串仍然是 s 。返回一个表示每个字符串片段的长度的列表。

示例 1:
输入:s = "ababcbacadefegdehijhklij"
输出:[9,7,8]
解释:
划分结果为 "ababcbaca"、"defegde"、"hijhklij" 。
每个字母最多出现在一个片段中。
像 "ababcbacadefegde", "hijhklij" 这样的划分是错误的,因为划分的片段数较少。 

示例 2:
输入:s = "eccbbbbdec"
输出:[10]

题解

直接上代码:

class Solution {
public:
    vector<int> partitionLabels(string s) {
        vector<int> last(26);
        int length = s.size();
        for (int i = 0; i < length; ++i) {
            last[s[i] - 'a'] = i;
        }
        vector<int> p;
        int start = 0, end = 0;
        for (int i = 0; i < length; ++i) {
            end = max(end, last[s[i] - 'a']);
            if (i == end) {
                p.emplace_back(end - start + 1);
                start = end + 1;
            }
        }

        return p;
    }
};

复杂度

时间复杂度: O ( n ) O(n) O(n)
空间复杂度: O ( 字母表 ) O(字母表) O(字母表)

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值