算法闭关修炼百题计划(五)

1.数组列表中的最大距离

给定 m 个数组,每个数组都已经按照升序排好序了。

现在你需要从两个不同的数组中选择两个整数(每个数组选一个)并且计算它们的距离。两个整数 a 和 b 之间的距离定义为它们差的绝对值 |a-b| 。

一开始用第一个元素sort了,这样反而会出错,因为一个元素的数组可能是其他数组的中间值,这种情况他应该和左右两端都比较才对
直接挨个比较左右,同步更新preMax和preMin

class Solution {
public:
    int maxDistance(vector<vector<int>>& arrays) {
        int preMin = arrays[0][0];
        int preMax = arrays[0].back();
        int ans = INT_MIN;
        for(int i = 1; i < arrays.size(); i ++){
            ans = max(ans, arrays[i].back() - preMin);
            ans = max(ans, preMax - arrays[i][0]);
            preMin = min(preMin, arrays[i][0]);
            preMax = max(preMax, arrays[i].back());
        }
        return ans;

    }
};

2.字符串的左右移

给定一个包含小写英文字母的字符串 s 以及一个矩阵 shift,其中 shift[i] = [direction, amount]:

  • direction 可以为 0 (表示左移)或 1 (表示右移)。
  • amount 表示 s 左右移的位数。
  • 左移 1 位表示移除 s 的第一个字符,并将该字符插入到 s 的结尾。
  • 类似地,右移 1 位表示移除 s 的最后一个字符,并将该字符插入到 s 的开头。

对这个字符串进行所有操作后,返回最终结果。

输入:s = “abc”, shift = [[0,1],[1,2]]
输出:“cab”
解释:
[0,1] 表示左移 1 位。 “abc” -> “bca”
[1,2] 表示右移 2 位。 “bca” -> “cab”

始终没有别人的代码优雅…

统一操作符之后用substr
其中s.substr(n - k)是取s从下标n-k开始一直到末尾的子串

class Solution {
public:
    string stringShift(string s, vector<vector<int>>& shift) {
        int k = 0;
        for (auto& v: shift) {
            if (v[0] == 0) k -= v[1];
            else k += v[1];
        }
        int n = s.size();
        k %= n;
        if (k < 0) k += n;
        return s.substr(n - k) + s.substr(0, n - k);
    }
};

3.相隔为1的编辑距离

可以插入,删除和替换,限制只能一次使得s==t,少一次都不行
所以注意sn == tn的情况,return的是flag,因为如果是true的话,flag一定是变化过一次的!

class Solution {
public:
    bool isOneInsert(string shorter, string longer){
        int sn = shorter.size();
        int ln = longer.size();
        int index1 = 0, index2 = 0;
        while(index1 < sn && index2 < ln){
            if(shorter[index1] == longer[index2]){
                index1++;
            }
            index2++;
            if(index2 - index1 > 1) return false;
        }
        return true;
    }
    bool isOneEditDistance(string s, string t) {
        int sn = s.size();
        int tn = t.size();
        if(sn - tn == 1){
            return isOneInsert(t, s);
        }
        else if(tn - sn == 1){
            return isOneInsert(s, t);
        }
        else if(tn == sn){
            bool flag = false;
            for(int i = 0; i < sn; i ++){
                if(s[i] != t[i]){
                    if(!flag){
                        flag = true;
                    }else{
                        return false;
                    }
                }
            }
            return flag;
        }
        else return false;
    }
};

4.形成字符串的最短路径

在这个问题中,我们得到了两个字符串,source 和 target。**我们需要用 source 最小数量的子 序列,让它们连起来等于 target。**如果无法做到,请返回 -1。

贪心

class Solution {
public:
    int shortestWay(string source, string target) {
        int ans = 0, i = 0, j;
        // 外部循环,直到目标字符串的指针 `i` 遍历完 `target` 字符串
        while(i < target.size()){
            // 保存当前的 `i` 位置,方便后续判断是否有无法匹配的字符
            j = i;

            // 遍历 `source` 字符串以匹配 `target` 中的字符
            for(auto &e : source){
                // 如果 `source` 当前字符 `e` 和 `target[i]` 相等
                if(e == target[i]) i ++; // 匹配到字符,`i` 向前移动,指向 `target` 的下一个字符
            }
            // 如果 `i` 没有前进,说明在 `source` 中找不到当前的 `target[i]` 字符
            if(i == j) return -1;
            ans++;
        }
        return ans;
    }
};

5.连接二进制表示可形成的最大数值

给你一个长度为 3 的整数数组 nums。

现以某种顺序 连接 数组 nums 中所有元素的 二进制表示 ,请你返回可以由这种方法形成的 最大 数值。

注意 任何数字的二进制表示 不含 前导零。

class Solution {
public:
    int f(int a, int b, int c){
        vector<int> res;
        while(a){
            res.push_back(a & 1);
            a /= 2;
        }
        while(b){
            res.push_back(b & 1);
            b /= 2;
        }
        while(c){
            res.push_back(c & 1);
            c /= 2;
        }
        reverse(res.begin(), res.end());//res是倒序存的!!
        int ans = 0;
        int n = res.size();
        for(int i = res.size() - 1; i >= 0; i --){
            if(res[i] == 1) ans += pow(2, res.size() - i - 1);
        }
        return ans;

    }
    int maxGoodNumber(vector<int>& nums) {
        int m = 0;
        m = max(m, f(nums[0], nums[1], nums[2]));
        m = max(m, f(nums[0], nums[2], nums[1]));
        m = max(m, f(nums[1], nums[0], nums[2]));
        m = max(m, f(nums[1], nums[2], nums[0]));
        m = max(m, f(nums[2], nums[0], nums[1]));
        m = max(m, f(nums[2], nums[1], nums[0]));
        return m;
    }
};
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值