【七月算法】day07 哈希表

970. 强整数

题目描述:

给定三个整数 x 、 y 和 bound ,返回 值小于或等于 bound 的所有 强整数 组成的列表 。

如果某一整数可以表示为 xi + yj ,其中整数 i >= 0 且 j >= 0,那么我们认为该整数是一个 强整数 。

你可以按 任何顺序 返回答案。在你的回答中,每个值 最多 出现一次。

思路:

先分别计算x,y的n次幂;

然后将x,y的n次幂的结果相加,放入到map中,可以去重;

将map的键值push到结果数组中;

其中注意1的情况;

class Solution {
public:
    vector<int> powerfulIntegers(int x, int y, int bound) {
        unordered_map<int, int> ans;
        vector<int> xval;
        vector<int> yval;
        vector<int> ret;
        
        for (int i = 0; pow(x,i) < bound; ++i) {
            xval.push_back(pow(x,i));
            if (x == 1) {
                break;
            }
        }
        
        for (int i = 0; pow(y,i) < bound; ++i) {
            yval.push_back(pow(y,i));
            if (y == 1) {
                break;
            }
        }
        
        for (int i = 0; i < xval.size(); ++i) {
            for (int j = 0; j < yval.size(); ++j) {
                int val = xval[i] + yval[j];
                if (val > bound) {
                    break;
                } else {
                    ans[val] = 1;
                }
            }
        }
        for (auto it = ans.begin(); it != ans.end(); ++it) {
            ret.push_back(it->first);
        }
        return ret;

    }
};

914. 卡牌分组

题目描述:

给定一副牌,每张牌上都写着一个整数。

此时,你需要选定一个数字 X,使我们可以将整副牌按下述规则分成 1 组或更多组:

每组都有 X 张牌。
组内所有的牌上都写着相同的整数。
仅当你可选的 X >= 2 时返回 true。

思路:

先统计每个数字出现的次数,找出最小的出现次数;

因为每组的牌值都一样,且每组的牌数从2开始到mingroup,每次对每个字母出现的次数进行求余,如果有余数存在,则说明当前的牌数分配不合理;

这道题也可以对所有的数字出现的次数求一个公约数,这个公约数如果大于等于2,则说明可以按照题目要求分配,否则返回false;

class Solution {
public:
    bool hasGroupsSizeX(vector<int>& deck) {
        unordered_map<int, int> ump;
        int mingroup = 10010;
        sort(deck.begin(),deck.end());
        for (int i = 0; i < deck.size(); ++i) {
            ump[deck[i]] ++;
        }
        for (auto it = ump.begin(); it != ump.end(); ++it) {
            mingroup = min(mingroup, it->second);
        }
        
        
        for (int i = 2; i <= mingroup; ++ i) {
            bool flag = true;
            for (auto it = ump.begin(); it != ump.end(); ++it) {
                if (it->second % i) {
                    flag = false;
                    break;
                }
            }
            if (flag) {
                return true;
            }

        }
        return false;   

    }
};

面试题 17.05. 字母与数字

题目描述:

给定一个放有字母和数字的数组,找到最长的子数组,且包含的字母和数字的个数相同。

返回该子数组,若存在多个最长子数组,返回左端点下标值最小的子数组。若不存在这样的数组,返回一个空数组。

思路:

前缀和+哈希表

用一个前缀和数组sum[i]表示前i项的和,如果是数字则权重加1,否则减1;
对于任意区间,sum[r]-sum[l-1]代表了[r,l]的和,当这个和为0时,表示数字和字母的个数相等;
于是,可以将等式进行一个转变,变成sum[r] == sum[l-1],这样需要将sum[l-1]插入哈希表,每次遍历的时候去哈希表里头找sum[r],找到一组满足条件的解,计算长度更新最大长度即可;

class Solution {
public:
    vector<string> findLongestSubarray(vector<string>& array) {
        int sum[100010]; //存前缀和
        unordered_map<int,int> hash;
        vector<string> ans;
        int pre = 0;
        for (int i = 0; i < array.size(); ++i) {
            sum[i] = pre;
            if (array[i][0] >= '0' && array[i][0] <= '9') {
                sum[i] ++;
            } else {
                sum[i] --;
            }
            pre = sum[i];
        }

        hash[0] = -1;
        int l = 0, r = -1, maxlen = 0; //记录最大长度,最大长度的左边界和右边界
        for (int i = 0; i < array.size(); ++i) {
            if (hash.find(sum[i]) != hash.end()) {
                int len = i - hash[sum[i]];
                if (len > maxlen) {
                    maxlen = len;
                    l = hash[sum[i]] + 1;
                    r = i;
                }
            } else {
                hash[sum[i]] = i;
            }
        }

        for (int i = l; i <= r; ++i) {
            ans.push_back(array[i]);
        }
        return ans;

    }
};
//重做

1497. 检查数组对是否可以被 k 整除

题目描述:

给你一个整数数组 arr 和一个整数 k ,其中数组长度是偶数,值为 n 。

现在需要把数组恰好分成 n / 2 对,以使每对数字的和都能够被 k 整除。

如果存在这样的分法,请返回 True ;否则,返回 False 。

思路:

先对所有数进行取余操作;(注意负数的情况)

余数为0的个数为奇数时,则必然不可能分成n/2队,直接返回false;

对比值i和k-i的个数是否相同,不相同则返回false;

否则返回true;

class Solution {
public:
    bool canArrange(vector<int>& arr, int k) {
        int n = arr.size();
        int hash[1000010]; //arr取余k之后的数字
        memset(hash, 0, sizeof(hash));
        for (int i = 0; i < n; ++i) {
            int mod = (arr[i]%k + k) % k;
            hash[mod] ++;
        }
        if (hash[0] & 1) {
            return false;
        }
        for (int i = 1; i < k; ++i) {
            if (hash[i] != hash[k-i]) {
                return false;
            }
        }
        return true;
        
    }
};

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值