day7:哈希表

454:四数相加II

把四个数组分为两个元组,先计算前两个中的X=a+b的值,将其存到哈希map中,并用umap[X]++计算X出现的次数。然后遍历后两个数组计算Y=0-(c+d)的值,(由于a+b+c+d=0),如果找到的话记录值并依次加到count,最后返回count。

int fourSumCount(vector<int>& nums1, vector<int>& nums2, vector<int>& nums3, vector<int>& nums4) {
        unordered_map<int,int> umap;
        for(int i=0;i<nums1.size();i++){
            for(int j=0;j<nums2.size();j++){
               int X=nums1[i]+nums2[j];
               umap[X]++;
            }
        }
        int count =0;
        for(int i=0;i<nums3.size();i++){
            for(int j=0;j<nums4.size();j++){
            int Y=0-(nums3[i]+nums4[j]);
        if (umap.find(Y) != umap.end()) {
            count+=umap[Y];
        }
          }
        }
        return count;
    }

383:赎金信

给定一个赎金信 (ransom) 字符串和一个杂志(magazine)字符串,判断第一个字符串 ransom 能不能由第二个字符串 magazines 里面的字符构成。如果可以构成,返回 true ;否则返回 false。

思路一:暴力法

在字符串magazines里面寻找是否有ransom中的字符,有则去除ransom中的该字符,遍历结束后检查ransom是否被清空,若清空则返回true,否则返回false。

 bool canConstruct(string ransomNote, string magazine) {
        for(int i=0;i<magazine.size();i++){
            for(int j=0;j<ransomNote.size();j++){
                if(ransomNote[j]==magazine[i]){
                    ransomNote.erase(ransomNote.begin()+j);
                    break;
                }
            }
        }
        if(ransomNote.size()==0){
            return true;
        }
        return false;
    }
思路二:哈希表法

用数组来存储比map更节省内存。通过recode数据记录 magazine里各个字符出现次数,遍历ransomNote,在record里对应的字符个数做–操作,如果数组中存在负数即小于零,说明ransomNote字符串总存在magazine中没有的字符,返回false,否则返回true。

  bool canConstruct(string ransomNote, string magazine) {
        int record[26] = {0};
        if (ransomNote.size() > magazine.size()) {
            return false;
        }
        for (int i = 0; i < magazine.length(); i++) {
            record[magazine[i]-'a'] ++;
        }
        for (int j = 0; j < ransomNote.length(); j++) {
            record[ransomNote[j]-'a']--;
            if(record[ransomNote[j]-'a'] < 0) {
                return false;
            }
        }
        return true;
    }

15:三数之和

vector<vector<int>> threeSum(vector<int>& nums) 
    {
        int size = nums.size();
        if (size < 3)   return {};          // 特判
        vector<vector<int> >res;            // 保存结果(所有不重复的三元组)
        std::sort(nums.begin(), nums.end());// 排序(默认递增)
        for (int i = 0; i < size; i++)      // 固定第一个数,转化为求两数之和
        {
            if (nums[i] > 0)    return res; // 第一个数大于 0,后面都是递增正数,不可能相加为零了
            // 去重:如果此数已经选取过,跳过
            if (i > 0 && nums[i] == nums[i-1])  continue;
            // 双指针在nums[i]后面的区间中寻找和为0-nums[i]的另外两个数
            int left = i + 1;
            int right = size - 1;
            while (left < right)
            {
                if (nums[left] + nums[right] > -nums[i])
                    right--;    // 两数之和太大,右指针左移
                else if (nums[left] + nums[right] < -nums[i])
                    left++;     // 两数之和太小,左指针右移
                else
                {
                    // 找到一个和为零的三元组,添加到结果中,左右指针内缩,继续寻找
                    res.push_back(vector<int>{nums[i], nums[left], nums[right]});
                    left++;
                    right--;
                    // 去重:第二个数和第三个数也不重复选取
                    // 例如:[-4,1,1,1,2,3,3,3], i=0, left=1, right=5
                    while (left < right && nums[left] == nums[left-1])  left++;
                    while (left < right && nums[right] == nums[right+1])    right--;
                }
            }
        }
        return res;
    }

18:四数之和

 vector<vector<int>> fourSum(vector<int>& nums, int target) {
        int size = nums.size();
        if (size < 3)   return {};          // 特判
        vector<vector<int> >res;            // 保存结果(所有不重复的三元组)
        sort(nums.begin(), nums.end());// 排序(默认递增)
        for(int k=0;k<size;k++){
            // 剪枝处理
            if (nums[k] > target && nums[k] >= 0) {
            	break; // 这里使用break,统一通过最后的return返回
            }
             // 对nums[k]去重
            if (k > 0 && nums[k] == nums[k - 1]) {
                continue;
            }
        for (int i = k+1; i < size; i++)      // 固定第一个数,转化为求两数之和
        {
            //剪枝
            if (nums[k] + nums[i] > target && nums[k] + nums[i] >= 0) {
                    break;
                }
            // 去重:如果此数已经选取过,跳过
            if (i > k+1 && nums[i] == nums[i-1])  continue;
            // 双指针在nums[i]后面的区间中寻找和为0-nums[i]的另外两个数
            int left = i + 1;
            int right = size - 1;
            while (left < right)
            {
                if ((long) nums[k] + nums[i] + nums[left] + nums[right] > target){
                    right--;    // 两数之和太大,右指针左移
                }
                else if((long) nums[k] + nums[i] + nums[left] + nums[right]  < target) {
                    left++;     // 两数之和太小,左指针右移
                }
                else
                {
                    // 找到一个和为零的三元组,添加到结果中,左右指针内缩,继续寻找
                    res.push_back(vector<int>{nums[k], nums[i], nums[left], nums[right]});
                    left++;
                    right--;
                    // 去重:第二个数和第三个数也不重复选取
                    // 例如:[-4,1,1,1,2,3,3,3], i=0, left=1, right=5
                    while (left < right && nums[left] == nums[left-1])  left++;
                    while (left < right && nums[right] == nums[right+1])    right--;
                }
            }
        }
        }
        return res;
    }
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值