LeetCode 每日一题 Day 195-202

2779. 数组的最大美丽值

给你一个下标从 0 开始的整数数组 nums 和一个 非负 整数 k 。

在一步操作中,你可以执行下述指令:

在范围 [0, nums.length - 1] 中选择一个 此前没有选过 的下标 i 。
将 nums[i] 替换为范围 [nums[i] - k, nums[i] + k] 内的任一整数。
数组的 美丽值 定义为数组中由相等元素组成的最长子序列的长度。

对数组 nums 执行上述操作任意次后,返回数组可能取得的 最大 美丽值。

注意:你 只 能对每个下标执行 一次 此操作。

数组的 子序列 定义是:经由原数组删除一些元素(也可能不删除)得到的一个新数组,且在此过程中剩余元素的顺序不发生改变。

示例 1:

输入:nums = [4,6,1,2], k = 2
输出:3
解释:在这个示例中,我们执行下述操作:

  • 选择下标 1 ,将其替换为 4(从范围 [4,8] 中选出),此时 nums = [4,4,1,2] 。
  • 选择下标 3 ,将其替换为 4(从范围 [0,4] 中选出),此时 nums = [4,4,1,4] 。
    执行上述操作后,数组的美丽值是 3(子序列由下标 0 、1 、3 对应的元素组成)。
    可以证明 3 是我们可以得到的由相等元素组成的最长子序列长度。
    示例 2:

输入:nums = [1,1,1,1], k = 10
输出:4
解释:在这个示例中,我们无需执行任何操作。
数组 nums 的美丽值是 4(整个数组)。

提示:

1 <= nums.length <= 1E5
0 <= nums[i], k <= 1E5
滑窗+排序:

class Solution {
public:
    int maximumBeauty(vector<int>& nums, int k) {
        ranges::sort(nums);
        int ans = 0, left = 0;
        for (int right = 0; right < nums.size(); right++) {
            while (nums[right] - nums[left] > k * 2) {
                left++;
            }
            ans = max(ans, right - left + 1);
        }
        return ans;
    }
};

521. 最长特殊序列 Ⅰ

给你两个字符串 a 和 b,请返回 这两个字符串中 最长的特殊序列 的长度。如果不存在,则返回 -1 。

「最长特殊序列」 定义如下:该序列为 某字符串独有的最长
子序列
(即不能是其他字符串的子序列) 。

字符串 s 的子序列是在从 s 中删除任意数量的字符后可以获得的字符串。

例如,“abc” 是 “aebdc” 的子序列,因为删除 “aebdc” 中斜体加粗的字符可以得到 “abc” 。 “aebdc” 的子序列还包括 “aebdc” 、 “aeb” 和 “” (空字符串)。

示例 1:

输入: a = “aba”, b = “cdc”
输出: 3
解释: 最长特殊序列可为 “aba” (或 “cdc”),两者均为自身的子序列且不是对方的子序列。
示例 2:

输入:a = “aaa”, b = “bbb”
输出:3
解释: 最长特殊序列是 “aaa” 和 “bbb” 。
示例 3:

输入:a = “aaa”, b = “aaa”
输出:-1
解释: 字符串 a 的每个子序列也是字符串 b 的每个子序列。同样,字符串 b 的每个子序列也是字符串 a 的子序列。

提示:

1 <= a.length, b.length <= 100
a 和 b 由小写英文字母组成
简单逻辑题,脑筋急转弯:

class Solution {
public:
    int findLUSlength(string a, string b) {
        if (a == b) {
            return -1;
        }
        return max(a.size(), b.size());
    }
};

522. 最长特殊序列 II

给定字符串列表 strs ,返回其中 最长的特殊序列 的长度。如果最长特殊序列不存在,返回 -1 。

特殊序列 定义如下:该序列为某字符串 独有的子序列(即不能是其他字符串的子序列)。

s 的 子序列可以通过删去字符串 s 中的某些字符实现。

例如,“abc” 是 “aebdc” 的子序列,因为您可以删除"aebdc"中的下划线字符来得到 “abc” 。“aebdc"的子序列还包括"aebdc”、 “aeb” 和 “” (空字符串)。

示例 1:

输入: strs = [“aba”,“cdc”,“eae”]
输出: 3
示例 2:

输入: strs = [“aaa”,“aaa”,“aa”]
输出: -1

提示:

2 <= strs.length <= 50
1 <= strs[i].length <= 10
strs[i] 只包含小写英文字母

枚举:


class Solution {
private:
    bool IsSub(const string& a, const string& b) {
        int i = 0;
        int j = 0;
        for (; i < a.size() && j < b.size(); ++j) {
            if (a[i] == b[j]) {
                ++i;
            }
        }
        return i == a.size();
    }

public:
    int findLUSlength(vector<string>& strs) {
        sort(strs.begin(), strs.end(), [](const string& a, const string& b) {
            return a.size() > b.size();
        });
        int n = strs.size();
        for (int i = 0; i < n; ++i) {
            int j = 0;
            for (; j < n; ++j) {
                if (i != j) {
                    if (IsSub(strs[i], strs[j])) {
                        break;
                    }
                }
            }
            if (j == n) {
                return strs[i].size();
            }
        }

        return -1;
    }
};

2288. 价格减免

句子 是由若干个单词组成的字符串,单词之间用单个空格分隔,其中每个单词可以包含数字、小写字母、和美元符号 ‘$’ 。如果单词的形式为美元符号后跟着一个非负实数,那么这个单词就表示一个 价格 。

例如 “$100”、“$23” 和 “ 6 " 表示价格,而 " 100 " 、 " 6" 表示价格,而 "100"、" 6"表示价格,而"100""” 和 "$1e5 不是。
给你一个字符串 sentence 表示一个句子和一个整数 discount 。对于每个表示价格的单词,都在价格的基础上减免 discount% ,并 更新 该单词到句子中。所有更新后的价格应该表示为一个 恰好保留小数点后两位 的数字。

返回表示修改后句子的字符串。

注意:所有价格 最多 为 10 位数字。

示例 1:

输入:sentence = “there are $1 2 a n d 5 2 and 5 2and5 candies in the shop”, discount = 50
输出:“there are $0.50 1.00 a n d 5 1.00 and 5 1.00and5 candies in the shop”
解释:
表示价格的单词是 “$1” 和 “$2” 。

  • “$1” 减免 50% 为 “$0.50” ,所以 “$1” 替换为 “$0.50” 。
  • “$2” 减免 50% 为 “$1” ,所以 “$2” 替换为 “$1.00” 。
    示例 2:

输入:sentence = “1 2 $3 4 $5 678 6 7 8 678 $9 10 10 10”, discount = 100
输出:“1 2 $0.00 4 $0.00 0.0078 0.00 7 8 0.0078 $0.00 10 10 10
解释:
任何价格减免 100% 都会得到 0 。
表示价格的单词分别是 “$3”、“$5”、“$6” 和 “$9”。
每个单词都替换为 “$0.00”。

提示:

1 <= sentence.length <= 105
sentence 由小写英文字母、数字、’ ’ 和 ‘$’ 组成
sentence 不含前导和尾随空格
sentence 的所有单词都用单个空格分隔
所有价格都是 正 整数且不含前导零
所有价格 最多 为 10 位数字
0 <= discount <= 100

灵神题解,忘记分割了:

class Solution {
public:
    string discountPrices(string sentence, int discount) {
        double d = 1 - discount / 100.0;
        stringstream ss(sentence);
        string ans, w;
        while (ss >> w) { // 一边分割,一边加到答案中
            if (!ans.empty()) {
                ans += ' ';
            }
            if (w.length() > 1 && w[0] == '$' && all_of(w.begin() + 1, w.end(), ::isdigit)) {
                stringstream s;
                s << fixed << setprecision(2) << '$' << stoll(w.substr(1)) * d;
                ans += s.str();
            } else {
                ans += w;
            }
        }
        return ans;
    }
};

题解:按空格分割+替换

2713. 矩阵中严格递增的单元格数(Hard)

给你一个下标从 1 开始、大小为 m x n 的整数矩阵 mat,你可以选择任一单元格作为 起始单元格 。

从起始单元格出发,你可以移动到 同一行或同一列 中的任何其他单元格,但前提是目标单元格的值 严格大于 当前单元格的值。

你可以多次重复这一过程,从一个单元格移动到另一个单元格,直到无法再进行任何移动。

请你找出从某个单元开始访问矩阵所能访问的 单元格的最大数量 。

返回一个表示可访问单元格最大数量的整数。

示例 1:
在这里插入图片描述

输入:mat = [[3,1],[3,4]]
输出:2
解释:上图展示了从第 1 行、第 2 列的单元格开始,可以访问 2 个单元格。可以证明,无论从哪个单元格开始,最多只能访问 2 个单元格,因此答案是 2 。
示例 2:
在这里插入图片描述

输入:mat = [[1,1],[1,1]]
输出:1
解释:由于目标单元格必须严格大于当前单元格,在本示例中只能访问 1 个单元格。
示例 3:
在这里插入图片描述

输入:mat = [[3,1,6],[-9,5,7]]
输出:4
解释:上图展示了从第 2 行、第 1 列的单元格开始,可以访问 4 个单元格。可以证明,无论从哪个单元格开始,最多只能访问 4 个单元格,因此答案是 4 。

提示:

m == mat.length
n == mat[i].length
1 <= m, n <= 1e5
1 <= m * n <= 1e5
-105 <= mat[i][j] <= 1e5

DP,hard菜鸡不会orz,灵神题解:

class Solution {
public:
    int maxIncreasingCells(vector<vector<int>>& mat) {
        int m = mat.size(), n = mat[0].size();
        map<int, vector<pair<int, int>>> g;
        for (int i = 0; i < m; i++) {
            for (int j = 0; j < n; j++) {
                g[mat[i][j]].emplace_back(i, j); // 相同元素放在同一组,统计位置
            }
        }

        vector<int> row_max(m), col_max(n);
        for (auto& [_, pos] : g) {
            // 先把所有 f 值都算出来,再更新 row_max 和 col_max
            vector<int> fs;
            for (auto& [i, j] : pos) {
                fs.push_back(max(row_max[i], col_max[j]) + 1);
            }
            for (int k = 0; k < pos.size(); k++) {
                auto& [i, j] = pos[k];
                row_max[i] = max(row_max[i], fs[k]); // 更新第 i 行的最大 f 值
                col_max[j] = max(col_max[j], fs[k]); // 更新第 j 列的最大 f 值
            }
        }
        return ranges::max(row_max);
    }
};

题解:动态规划+优化

2748. 美丽下标对的数目

给你一个下标从 0 开始的整数数组 nums 。如果下标对 i、j 满足 0 ≤ i < j < nums.length ,如果 nums[i] 的 第一个数字 和 nums[j] 的 最后一个数字 互质 ,则认为 nums[i] 和 nums[j] 是一组 美丽下标对 。

返回 nums 中 美丽下标对 的总数目。

对于两个整数 x 和 y ,如果不存在大于 1 的整数可以整除它们,则认为 x 和 y 互质 。换而言之,如果 gcd(x, y) == 1 ,则认为 x 和 y 互质,其中 gcd(x, y) 是 x 和 y 的 最大公因数 。

示例 1:

输入:nums = [2,5,1,4]
输出:5
解释:nums 中共有 5 组美丽下标对:
i = 0 和 j = 1 :nums[0] 的第一个数字是 2 ,nums[1] 的最后一个数字是 5 。2 和 5 互质,因此 gcd(2,5) == 1 。
i = 0 和 j = 2 :nums[0] 的第一个数字是 2 ,nums[2] 的最后一个数字是 1 。2 和 1 互质,因此 gcd(2,1) == 1 。
i = 1 和 j = 2 :nums[1] 的第一个数字是 5 ,nums[2] 的最后一个数字是 1 。5 和 1 互质,因此 gcd(5,1) == 1 。
i = 1 和 j = 3 :nums[1] 的第一个数字是 5 ,nums[3] 的最后一个数字是 4 。5 和 4 互质,因此 gcd(5,4) == 1 。
i = 2 和 j = 3 :nums[2] 的第一个数字是 1 ,nums[3] 的最后一个数字是 4 。1 和 4 互质,因此 gcd(1,4) == 1 。
因此,返回 5 。
示例 2:

输入:nums = [11,21,12]
输出:2
解释:共有 2 组美丽下标对:
i = 0 和 j = 1 :nums[0] 的第一个数字是 1 ,nums[1] 的最后一个数字是 1 。gcd(1,1) == 1 。
i = 0 和 j = 2 :nums[0] 的第一个数字是 1 ,nums[2] 的最后一个数字是 2 。gcd(1,2) == 1 。
因此,返回 2 。

提示:

2 <= nums.length <= 100
1 <= nums[i] <= 9999
nums[i] % 10 != 0

暴力枚举能做:

class Solution {
public:
    int countBeautifulPairs(vector<int>& nums) {
        int res = 0, n = nums.size();
        for (int i = 0; i < n; i++) {
            while (nums[i] >= 10) {
                nums[i] /= 10;
            }
            for (int j = i + 1; j < n; j++) {
                if (gcd(nums[i], nums[j] % 10) == 1) {
                    res++;
                }
            }
        }
        return res;
    }
};

LCP 61. 气温变化趋势

力扣城计划在两地设立「力扣嘉年华」的分会场,气象小组正在分析两地区的气温变化趋势,对于第 i ~ (i+1) 天的气温变化趋势,将根据以下规则判断:

若第 i+1 天的气温 高于 第 i 天,为 上升 趋势
若第 i+1 天的气温 等于 第 i 天,为 平稳 趋势
若第 i+1 天的气温 低于 第 i 天,为 下降 趋势
已知 temperatureA[i] 和 temperatureB[i] 分别表示第 i 天两地区的气温。 组委会希望找到一段天数尽可能多,且两地气温变化趋势相同的时间举办嘉年华活动。请分析并返回两地气温变化趋势相同的最大连续天数。

即最大的 n,使得第 i~i+n 天之间,两地气温变化趋势相同

示例 1:

输入: temperatureA = [21,18,18,18,31] temperatureB = [34,32,16,16,17]

输出:2

解释:如下表所示, 第 2~4 天两地气温变化趋势相同,且持续时间最长,因此返回 4-2=2
在这里插入图片描述

示例 2:

输入: temperatureA = [5,10,16,-6,15,11,3] temperatureB = [16,22,23,23,25,3,-16]

输出:3

提示:

2 <= temperatureA.length == temperatureB.length <= 1000
-20 <= temperatureA[i], temperatureB[i] <= 40
按照题目要求遍历:

class Solution {
public:
    int temperatureTrend(vector<int>& temperatureA, vector<int>& temperatureB) {
        int ans = 0, f = 0;
        for (int i = 0; i < temperatureA.size() - 1; i++) {
            int x = temperatureA[i + 1] - temperatureA[i];
            int y = temperatureB[i + 1] - temperatureB[i];
            if (x == 0 && y == 0 || x * y > 0){
                ans = max(ans , ++f);
            }
            else {
                f = 0;
            }
        }
        return ans;
    }
};
  • 18
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

XforeverZ

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值