c++ 数据结构——哈希表

1.哈希表的用法:

https://blog.csdn.net/sevenjoin/article/details/81943864

2.相关题目:

2.1 leetcode 1 —— Two Sum

class Solution {
public:
    vector<int> twoSum(vector<int>& nums, int target) {
        map<int,int> m;
        vector<int> res(2,-1);
        for(int i = 0;i < nums.size();i++)
        {
            if(i > 0)
            {
                if(m.count(target - nums[i]) > 0)
                {
                    res[0] = m[target - nums[i]];
                    res[1] = i;
                    break;
                }
            }
            m[nums[i]] = i;
        }
              
        return res;
    }
    
};

2.2 leetcode 3 —— Longest Substring Without Repeating Characters

class Solution {
public:
    int lengthOfLongestSubstring(string s) {
        map<char, int> ss;
        int ans = 0,i = 0,j = 0,n = s.size();
        map<char, int>::iterator iter;
        for(;j < n;j++)
        {
            iter = ss.find(s[j]);
            if(iter != ss.end()) //找到了,需要重新设置i
            {
                i = max(i ,iter->second + 1);
            }
            ans = max(ans,j - i + 1);
            ss[s[j]] = j;
        }
        return ans;
    }
};

2.3 leetcode 36 —— Valid Sudoku

用set做更简单~

class Solution {
public:
    bool isValidSudoku(vector<vector<char>>& board) {
        vector<set<int>> rows(9);
        vector<set<int>> cols(9);
        vector<set<int>> boxes(9);
        
        for(int i = 0;i < 9;i++)
        {
            for(int j = 0;j < 9;j++)
            {
                if(board[i][j] == '.') continue;
                
                if(rows[i].count(board[i][j] - '0') > 0) return false;
                else
                {
                    rows[i].insert(board[i][j] - '0');
                }
                
                if(cols[j].count(board[i][j] - '0') > 0) return false;
                else
                {
                    cols[j].insert(board[i][j] - '0');
                }
                
                int tmp = (i / 3) * 3 + j / 3;
                if(boxes[tmp].count(board[i][j] - '0') > 0) return false;
                else
                {
                    boxes[tmp].insert(board[i][j] - '0');
                }
                
            }
            
        }
        return true;
    }
};

2.4 leetcode 49 —— Group Anagrams

参考:https://leetcode-cn.com/problems/group-anagrams/solution/zi-mu-yi-wei-ci-fen-zu-by-leetcode/

方法1:

排序字符串并分类,时间复杂度O(NKlogK),空间复杂度O(NK)

class Solution {
public:
    vector<vector<string>> groupAnagrams(vector<string>& strs) {
        vector<vector<string>> res;
        map<vector<char>, vector<string>> mmap;
        for(string s : strs)
        {
            vector<char> tmp_c;
            for(char c : s)
            {
                tmp_c.push_back(c);
            }
            sort(tmp_c.begin(),tmp_c.end());
            mmap[tmp_c].push_back(s);
        }
        map<vector<char>, vector<string>>::iterator iter = mmap.begin();
        for(;iter != mmap.end();++iter)
        {
            res.push_back(iter->second);
        }
        return res;
    }
};

方法2:

class Solution {
public:
    vector<vector<string>> groupAnagrams(vector<string>& strs) {
        map<string, vector<string>> mmap;
        for(string s : strs)
        {
            vector<int> nums(26, 0);
            for(char c : s)
            {
                nums[c - 'a']++;
            }
            string s_tmp;
            for(int i : nums)
            {
                s_tmp += to_string(i) + "#";
            }
            mmap[s_tmp].push_back(s);
        }
        vector<vector<string>> res;
        for(auto it : mmap)
        {
            res.push_back(it.second);
        }
        return res;
    }
};

2.5 leetcode 76 —— Minimum Window Substring

参考链接(写的非常好!!!):https://leetcode-cn.com/problems/minimum-window-substring/solution/hua-dong-chuang-kou-suan-fa-tong-yong-si-xiang-by-/

用unordered_map会更快。

class Solution {
public:
    string minWindow(string s, string t) {
        unordered_map<char, int> windows;
        unordered_map<char, int> needs;
        for(char c : t) //记录t中每个字符的出现次数
        {
            needs[c]++;
        }
        
        int left = 0,right = 0,count = 0;
        int start = 0,len = INT_MAX;
        while(right < s.size())
        {
            char c = s[right];
            if(needs.count(c))
            {
                windows[c]++;//记录窗口里有多少个这个字符
                if(windows[c] == needs[c])
                {
                    count++;
                }
            }
            right++;
            
            while(count == needs.size())
            {
                if(len > right - left)
                {
                    start = left;//记录最优的开始位置
                    len = right - left;
                }
                char c1 = s[left];
                if(windows.count(c1))
                {
                    windows[c1]--;
                    if(windows[c1] < needs[c1])
                        count--;
                }
                left++;
            }
        }
        if(len == INT_MAX) return "";
        return s.substr(start,len);
    }
};

2.6 leetcode 438 —— Find All Anagrams in a String

class Solution {
public:
    vector<int> findAnagrams(string s, string p) {
        vector<int> ans;
        int left = 0,right = 0,count = 0;
        unordered_map<char, int> windows;
        unordered_map<char, int> needs;
        for(char c : p)
        {
            needs[c]++;
        }        
        
        
        while(right < s.size())
        {
            char c1 = s[right];
            
            if(needs.count(c1))
            {
                windows[c1]++;
                if(windows[c1] == needs[c1])
                {
                    count++;
                }                
            }
            
            right++;
            
            while(count == needs.size())
            {
                
                if((right - left) == p.size())
                {
                    ans.push_back(left);
                }
                char c2 = s[left];
                if(windows.count(c2))
                {
                    windows[c2]--;
                    if(windows[c2] < needs[c2])
                    {
                        count--;
                    }
                }
                left++;
            }
        }
        return ans;
    }
};

2.7 leetcode 149 —— Max Points on a Line

参考:

https://leetcode-cn.com/problems/max-points-on-a-line/solution/zhi-xian-shang-zui-duo-de-dian-shu-by-leetcode/

class Solution {
public:
    int gcd(int x,int y)
    {
        if(y == 0) return x;
        return gcd(y, x % y);
    }
    int maxPoints(vector<vector<int>>& points) {
        int N = points.size();
        if(N < 3) return N;
        int res = 0;
        int dup = 0,dx = 0,dy = 0,tmp = 0;
        map<pair<int,int>, int> line;
        for(int i = 0;i < N - 1;i++)
        {
            line.clear();
            dup = 1;
            tmp = 0;
            for(int j = i + 1;j < N;j++)
            {
                dx = points[j][0] - points[i][0];
                dy = points[j][1] - points[i][1];
                if(dx == 0 && dy == 0) dup++;
                else
                {
                    int g = gcd(dx,dy);
                    ++line[{dx/g,dy/g}];
                }
            }
            for(auto l : line)
            {
                if(tmp < l.second)
                    tmp = l.second;
            }
            if(tmp + dup > res) res = tmp + dup;
        }
        return res;
    }
};

2.8 leetcode 166 —— Fraction to Recurring Decimal

class Solution {
public:
    string fractionToDecimal(int numerator, int denominator) {
        string res;
        if(denominator == 0)    return res;
        if(numerator < 0 && denominator > 0 || numerator > 0 && denominator < 0)//处理结果是负数的情况
            res += "-";
        long num = static_cast<long>(numerator);
        long denom = static_cast<long>(denominator);
        num = abs(num);
        denom = abs(denom);//求绝对值
        res += to_string(num / denom);
        num %= denom;
        if(num != 0) res += ".";
        int count = 0;//代表当前商对应的小数点后位数,从1开始加入res
        unordered_map<long,int> mmap;
        while(num != 0 && !mmap.count(num))//余数相等则出现循环小数
        {
            mmap[num] = count;
            count++;
            num *= 10;//新的除数
            res += to_string(num / denom);
            num %= denom;//新的余数 
        }
        if(mmap.count(num))//如果新的余数和之前出现的相同
        {
            res += "()";
            int cur = res.size()-2;// '(' 也为count位置
            while(count-- > mmap[num])//如果最后一位小数位数不为重复余数对应的位数
            {
                swap(res[cur],res[cur - 1]);
                cur--;
            }
        }
        return res;
    }
};

2.9 leetcode 136 —— Single Number

哈希表方法:

class Solution {
public:
    int singleNumber(vector<int>& nums) {
        int res;
        unordered_map<int,int> mmap;
        for(int i = 0;i < nums.size();i++)
        {
            mmap[nums[i]]++;
        }
        for(auto p : mmap)
        {
            if(p.second == 1)
                res = p.first;
        }
        return res;
    }
};

异或方法:

class Solution {
public:
    int singleNumber(vector<int>& nums) {
        int res = nums[0];
        for(int i = 1;i < nums.size();i++)
        {
            res ^= nums[i];
        }
        return res;
    }
};

2.10 leetcode 347 —— Top K Frequent Elements

class Solution {
    typedef pair<int,int> IIpair;
    
    struct cmp
    {
        bool operator()(const IIpair &a, const IIpair &b)
        {
            return a.second > b.second;//小顶堆
        }
    };
    
public:
    
    vector<int> topKFrequent(vector<int>& nums, int k) {
        vector<int> res(k);
        unordered_map<int,int> mmap;
        priority_queue<IIpair,vector<IIpair>,cmp> q;
        for(int i = 0;i < nums.size();i++)
        {
            mmap[nums[i]]++;
        }
        
        for(auto p : mmap)
        {
            if(q.size() < k)
            {
                q.push(p);
            }
            else if(p.second > q.top().second)
            {
                q.pop();
                q.push(p);
            }
        }
        
        for(int i = k - 1;i >= 0;i--)
        {
            res[i] = q.top().first;
            q.pop();
        }
        
        return res;
    }
};

2.11 leetcode 202 —— Happy Number

class Solution {
public:
    bool isHappy(int n) {
        set<int> sset;
        while(n != 1)
        {
            int sum = 0;
            while(n != 0)
            {
                sum += pow(n % 10, 2);
                n /= 10;
            }
            n = sum;
            if(sset.count(n)) return false;
            sset.insert(n);
        }
        
        return true;
    }
};

2.12 leetcode 204 —— Count Primes

厄拉多塞筛法:(虽然和hashmap没关系。。。)时间最快

bool类型实际上是int型

class Solution {
public:
    int countPrimes(int n) {
        if(n < 2) return 0;
        vector<bool> tmp(n - 1,true);
        tmp[0] = false;
        int count = 0;
        for(int i = 2;i <= n / 2;i++)
        {
            if(tmp[i - 1] == false) continue;
            for(int k = i;k <= n / i;k++)
            {                
                long p = i * k;
                if(p < n)
                {
                    tmp[p - 1] = false;
                }
            }
        }
        
        for(int i = 0;i < n - 1;i++)
        {
            if(tmp[i] == true) count++;
        }
        return count;
    }
};

2.13 leetcode 217 —— Contains Duplicate

class Solution {
public:
    bool containsDuplicate(vector<int>& nums) {
        unordered_set<int> sset;
        for(int i = 0;i < nums.size();i++)
        {
            if(sset.count(nums[i]) != 0) return true;
            sset.insert(nums[i]);
        }
        return false;
    }
};

2.14 leetcode 242 —— Valid Anagram

class Solution {
public:
    bool isAnagram(string s, string t) {
        if(s.size() != t.size()) return false;
        map<char,int> mmap1;
        map<char,int> mmap2;
        for(int i = 0;i < s.size();i++)
        {
            mmap1[s[i]]++;
            mmap2[t[i]]++;
        }
        
        auto iter1 = mmap1.begin();
        auto iter2 = mmap2.begin();
        while(iter1 != mmap1.end() && iter2 != mmap2.end())
        {
            if(iter1->first != iter2->first || iter1->second != iter2->second) return false;
            ++iter1,++iter2;
        }
        if(iter1 == mmap1.end() && iter2 == mmap2.end())
        {
            return true;
        }
        
        return false;
    }
};

2.15 leetcode 350 —— Intersection of Two Arrays II

class Solution {
public:
	vector<int> intersect(vector<int>& nums1, vector<int>& nums2) {
		unordered_map<int, int> mmap;
		int n1 = nums1.size();
		int n2 = nums2.size();
		vector<int> res;
		if (n1 <= n2)
		{
			for (int i = 0; i < n2; i++)
			{
				mmap[nums2[i]]++;
			}

			for (int i = 0; i < n1; i++)
			{
				if (mmap[nums1[i]] > 0)
				{
					mmap[nums1[i]]--;
					res.push_back(nums1[i]);
				}
			}
		}
		else
		{
			for (int i = 0; i < n1; i++)
			{
				mmap[nums1[i]]++;
			}

			for (int i = 0; i < n2; i++)
			{
				if (mmap[nums2[i]] > 0)
				{
					mmap[nums2[i]]--;
					res.push_back(nums2[i]);
				}
			}
		}

		return res;
	}
};

顺便附上349 Intersection of Two Arrays 的答案:

class Solution {
public:
    vector<int> intersection(vector<int>& nums1, vector<int>& nums2) {
        unordered_map<int, int> mmap;
		int n1 = nums1.size();
		int n2 = nums2.size();
		vector<int> res;
		if (n1 <= n2)
		{
			for (int i = 0; i < n2; i++)
			{
				mmap[nums2[i]]++;
			}

			for (int i = 0; i < n1; i++)
			{
                auto iter = mmap.find(nums1[i]);
				if (iter != mmap.end())
				{                    
					res.push_back(nums1[i]);
                    mmap.erase(iter);
				}
			}
		}
		else
		{
			for (int i = 0; i < n1; i++)
			{
				mmap[nums1[i]]++;
			}

			for (int i = 0; i < n2; i++)
			{
				auto iter = mmap.find(nums2[i]);
				if (iter != mmap.end())
				{                    
					res.push_back(nums2[i]);
                    mmap.erase(iter);
				}
			}
		}

		return res;
    }
};

2.16 leetcode 387 —— First Unique Character in a String

class Solution {
public:
    int firstUniqChar(string s) {
        int res = -1;
        unordered_map<char,int> mmap;
        for(int i = 0;i < s.size();i++)
        {
            mmap[s[i]]++;
        }
        
        for(int i = 0;i < s.size();i++)
        {
            if(mmap[s[i]] == 1)
            {   
                res = i;
                break;
            }
        }
        return res;
    }
};

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值