【简单】389. 找不同

【题目】
给定两个字符串 s 和 t,它们只包含小写字母。字符串 t 由字符串 s 随机重排,然后在随机位置添加一个字母。请找出在 t 中被添加的字母。
来源:leetcode
链接:https://leetcode-cn.com/problems/find-the-difference/
【示例】
【方法一:太机智了】
执行用时 :0 ms, 在所有 C++ 提交中击败了100.00% 的用户
内存消耗 :6.8 MB, 在所有 C++ 提交中击败了100.00%的用户

class Solution {
public:
    char findTheDifference(string s, string t) {
        int sum = 0;
        for (auto i : t)
            sum += i;
        for (auto i : s)
            sum -= i;
        return sum;
    }
};

【方法二】

class Solution {
public:
    int hashchar[26]={0};
    char findTheDifference(string s, string t) {
        s+=t;
        for(auto c:s)
            hashchar[c-'a']++;
        for(int i=0;i<26;i++)
            if(hashchar[i]%2)
                return 'a'+i;
        return 'a';
    }
};

【方法三:常规】

class Solution {
public:
    char findTheDifference(string s, string t) {
        int len=s.size();
        sort(s.begin(),s.end());
        sort(t.begin(),t.end());
        for(int i=0;i<len;i++)
            if(s[i]!=t[i])
                return t[i];
        return t[len];
    }
};
namespace hash_bucket { template<class T> struct HashBucketNode { T _data; HashBucketNode<T>* _next; HashBucketNode(const T& data) :_data(data) ,_next(nullptr) {} }; // K 为 T 中key的类型 // T 可能是键值对,也可能是K // KeyOfT: 从T中提取key // Hash将key转化为整形,因为哈市函数使用除留余数法 template<class K, class T, class KeyOfT, class Hash> class HashBucket { typedef HashBucketNode<T> Node; public: HashBucket() { _tables.resize(10, nullptr); } // 哈希桶的销毁 ~HashBucket() { for (size_t i = 0; i < _tables.size(); i++) { Node* cur = _tables[cur]; while (cur) { Node* next = cur->_next; delete cur; cur = next; } } } /********************************************************************/ unsigned long __stl_next_prime(unsigned long n) { // Note: assumes long is at least 32 bits. static const int __stl_num_primes = 28; static const unsigned long __stl_prime_list[__stl_num_primes] = { 53, 97, 193, 389, 769, 1543, 3079, 6151, 12289, 24593, 49157, 98317, 196613, 393241, 786433, 1572869, 3145739, 6291469, 12582917, 25165843, 50331653, 100663319, 201326611, 402653189, 805306457, 1610612741, 3221225473, 4294967291 }; const unsigned long* first = __stl_prime_list; const unsigned long* last = __stl_prime_list + __stl_num_primes; const unsigned long* pos = lower_bound(first, last, n); return pos == last ? *(last - 1) : *pos; } /********************************************************************/ // 插入值为data的元素,如果data存在则不插入 bool Insert(const T& data) { KeyOfT kot; Hash hash; if (_n == _tables.size()) { vector<Node*> newTables(__stl_next_prime(_tables.size() + 1), nullptr); for (size_t i = 0; i < _tables.size(); i++) { Node* cur = _tables[cur]; while (cur) { Node* next = cur->_next; size_t hashi = hash(kot(cur->_data)) % newTables.size(); cur->_next = newTables[hashi]; newTables[hashi] = cur; cur = next; } _tables[hashi] = nullptr; } _tables.swap(newTables); } size_t hashi = hash(kot(data)) % _tables.size(); Node* newnode = new Node(data); newnode->_next = _tables[hashi]; _tables[hashi] = newnode; ++_n; return true; } // 在哈希桶中查值为key的元素,存在返回true否则返回false bool Find(const K& key) { KeyOfT kot; Hash hash; size_t hashi = hash(key) % _tables.size(); Node* cur = _tables[hashi]; while (cur) { if (kot(cur->_data) == key) { return true; } cur = cur->_next; } return false; } // 哈希桶中删除key的元素,删除成功返回true,否则返回false bool Erase(const K& key) { KeyOfT kot; Hash hash; size_t hashi = hash(key) % _tables.size(); Node* cur = _tables[hashi]; Node* prev = nullptr; while (cur) { if (kot(cur->_data) == key) { if (prev == nullptr) { _tables[hashi] = nullptr; } else { prev->_next = cur->_next; delete cur; --_n; return true; } } prev = cur; cur = cur->_next; } return false; } private: vector<Node*> _tables; // 指针数组 size_t _n = 0; // 表中存储数据个数 }; /***************************************************************************************************************************/ // 为了实现简单,在哈希桶的迭代器类中需要用到hashBucket本身, template<class K, class V, class KeyOfValue, class HF> class HashBucket; // 注意:因为哈希桶在底层是单链表结构,所以哈希桶的迭代器不需要--操作 template <class K, class V, class KeyOfValue, class HF> struct HBIterator { typedef HashBucket<K, V, KeyOfValue, HF> HashBucket; typedef HashBucketNode<V>* PNode; typedef HBIterator<K, V, KeyOfValue, HF> Self; HBIterator(PNode pNode = nullptr, HashBucket* pHt = nullptr) :_pNode(PNode) ,_pHt(pHt) {} Self& operator++() { // 当前迭代器所指节点后还有节点时直接取其下一个节点 if (_pNode->_pNext) _pNode = _pNode->_pNext; else { // 下一个不空的桶,返回该桶中第一个节点 size_t bucketNo = _pHt->HashFunc(KeyOfValue()(_pNode->_data)) + 1; for (; bucketNo < _pHt->BucketCount(); ++bucketNo) { if (_pNode = _pHt->_ht[bucketNo]) break; } } return *this; } Self operator++(int) { } V& operator*(); V* operator->(); bool operator==(const Self& it) const; bool operator!=(const Self& it) const; PNode _pNode; // 当前迭代器关联的节点 HashBucket* _pHt; // 哈希桶--主要是为了下一个空桶时候方便 }; // unordered_map中存储的是pair<K, V>的键值对,K为key的类型,V为value的类型,HF哈希函数类型 // unordered_map在实现时,只需将hashbucket中的接口重新封装即可 template<class K, class V, class HF = DefHashF<K>> class unordered_map { typedef HashBucket<K, pair<K, V>, KeyOfValue, HF> HT; // 通过key获取value的操作 struct KeyOfValue { const K& operator()(const pair<K, V>& data) { return data.first; } }; public: typename typedef HT::Iterator iterator; public: unordered_map() : _ht() {} //////////////////////////////////////////////////// iterator begin() { return _ht.begin(); } iterator end() { return _ht.end(); } //////////////////////////////////////////////////////////// // capacity size_t size()const { return _ht.size(); } bool empty()const { return _ht.empty(); } /////////////////////////////////////////////////////////// // Acess V& operator[](const K& key) { pair<iterator, bool> ret = _ht.InsertUnique(pair<K, V>(key, V())); return ret.fisrt->second; } const V& operator[](const K& key)const; ////////////////////////////////////////////////////////// // lookup iterator find(const K& key) { return _ht.Find(key); } size_t count(const K& key) { return _ht.Count(key); } ///////////////////////////////////////////////// // modify pair<iterator, bool> insert(const pair<K, V>& valye) { return _ht.Insert(valye); } iterator erase(iterator position) { return _ht.Erase(position); } //////////////////////////////////////////////////////////// // bucket size_t bucket_count() { return _ht.BucketCount(); } size_t bucket_size(const K& key) { return _ht.BucketSize(key); } private: HT _ht; };如何编写Self operator++(int)
最新发布
07-10
<think>我们正在处理一个哈希桶迭代器的后置++运算符重载(operator++(int))。后置++与前置++的区别在于,后置++需要返回增加前的值,而前置++返回增加后的值。因此,后置++通常需要先保存当前状态,然后调用前置++进行增加,最后返回保存的原始状态。 在给定的代码框架中,前置++(operator++)已经实现。我们可以利用前置++来实现后置++。 具体步骤: 1. 创建一个临时对象,保存当前迭代器的状态(即*this)。 2. 使用前置++将当前迭代器移动到下一个位置。 3. 返回保存的临时对象(即未移动之前的迭代器)。 注意:后置++的返回值类型应该是迭代器的值(而不是引用),并且参数中有一个int(用于区分前置++)。 根据以上思路,我们可以编写如下代码: ```cpp Self operator++(int) { Self tmp(*this); // 保存当前状态 ++(*this); // 调用前置++,移动当前迭代器到下一个位置 return tmp; // 返回保存的临时对象 } ``` 但是,请注意,在上面的代码中,我们调用了前置++,而前置++的实现(operator++())中已经处理了两种情况:当前桶中还有下一个节点,或者需要寻下一个非空桶。因此,我们可以复用前置++的逻辑。 另外,需要确保前置++已经正确实现。根据提供的前置++代码: ```cpp Self& operator++() { // 当前迭代器所指节点后还有节点时直接取其下一个节点 if (_pNode->_pNext) _pNode = _pNode->_pNext; else { // 下一个不空的桶,返回该桶中第一个节点 size_t bucketNo = _pHt->HashFunc(KeyOfValue()(_pNode->_data)) + 1; for (; bucketNo < _pHt->BucketCount(); ++bucketNo) { if (_pNode = _pHt->_ht[bucketNo]) break; } } return *this; } ``` 这里有一个小错误:在寻下一个非空桶时,应该将桶号从当前桶的下一个开始遍历,直到到非空桶。但是,当前桶号是通过对当前节点的键值进行哈希计算得到的,然后加1。但是,如果当前节点已经是桶中的最后一个节点,那么我们需要从下一个桶开始。注意,这里桶号的计算应该是基于当前节点的哈希值,但是当前节点在哪个桶中?实际上,我们不应该重新计算当前节点的桶号,因为迭代器中已经保存了哈希表指针(_pHt),我们可以通过当前节点所在的桶来定位下一个桶。 然而,在迭代器结构中,我们并没有直接存储当前桶号。因此,前置++的实现中,在寻下一个非空桶时,需要从当前桶的下一个桶开始遍历(即当前节点所在桶的下一个桶)。但是,代码中却是通过重新计算当前节点的哈希值得到桶号,然后加1。这可能会导致问题,因为如果哈希表已经扩容,那么同一个节点在新表中计算的桶号可能不同。所以,更好的做法是记录当前桶号,然后从当前桶的下一个桶开始。 不过,由于问题要求我们编写后置++,而前置++已经这样实现,我们暂且认为前置++是正确的(或者按照给定的代码来)。 因此,后置++的实现如下: ```cpp Self operator++(int) { Self tmp = *this; ++(*this); return tmp; } ``` 但是,请注意,在给定的前置++代码中,有一个笔误:在else分支中,赋值语句和条件语句混在一起,应该使用比较而不是赋值。正确的代码应该是: ```cpp if (_pNode = _pHt->_ht[bucketNo]) // 这里应该是赋值,因为目的是将桶中的节点赋给_pNode,然后判断是否为空 ``` 但是,这行代码的意图是:如果桶非空,则将桶中的第一个节点赋给_pNode,并跳出循环。所以,这里使用赋值语句是故意的,但这样写容易引起误解,而且如果桶为空,则不会进入if,继续循环。所以,我们暂时不修改前置++,因为问题焦点在后置++。 综上所述,我们编写后置++运算符如下: ```cpp Self operator++(int) { Self tmp(*this); ++(*this); // 调用前置自增 return tmp; } ``` 注意:由于迭代器类中已经定义了拷贝构造函数(使用编译器生成的),所以这里可以直接使用拷贝构造创建临时对象。 最后,将这段代码放入迭代器类中。 另外,需要补充迭代器类中的其他成员函数(如operator*,operator->等),但问题只要求编写operator++(int),所以其他部分我们忽略。 因此,完整的迭代器类中后置++的实现如下: ```cpp template <class K, class V, class KeyOfValue, class HF> struct HBIterator { // ... 其他成员 Self& operator++() { // 前置++的实现(已有) // ... } Self operator++(int) { Self tmp(*this); ++(*this); return tmp; } // ... 其他成员 }; ``` 注意:在实现后置++时,确保前置++已经正确定义。</think>在 `HBIterator` 类中实现后置自增运算符 `operator++(int)` 的方法如下: ```cpp Self operator++(int) { Self tmp(*this); // 保存当前状态 ++(*this); // 调用前置++实现核心逻辑 return tmp; // 返回原始状态 } ``` ### 关键点说明: 1. **保存当前状态**:创建临时副本 `tmp` 存储当前迭代器状态 2. **调用前置++**:通过 `++(*this)` 复用已实现的前置自增逻辑 3. **返回原始值**:返回保存的临时副本(符合后置++语义) 4. **参数 `int`**:使用哑元参数 `int` 区分前置/后置版本 ### 完整迭代器类修正: ```cpp template <class K, class V, class KeyOfValue, class HF> struct HBIterator { // ... 其他成员不变 ... Self& operator++() // 前置++ { if (_pNode->_pNext) { _pNode = _pNode->_pNext; } else { size_t bucketNo = _pHt->HashFunc(KeyOfValue()(_pNode->_data)) + 1; for (; bucketNo < _pHt->BucketCount(); ++bucketNo) { if (_pNode = _pHt->_ht[bucketNo]) break; } } return *this; } Self operator++(int) // 后置++ { Self tmp(*this); ++(*this); return tmp; } }; ``` ### 使用示例: ```cpp unordered_map<int, string> map; auto it = map.begin(); it++; // 调用后置++ ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值