算法日常刷题笔记(7)

第一天

字符串反转

字符串及其反转中是否存在同一子字符串https://leetcode.cn/problems/existence-of-a-substring-in-a-string-and-its-reverse/

给你一个字符串 s ,请你判断字符串 s 是否存在一个长度为 2 的子字符串,在 s 反转后的字符串中也出现。

如果存在这样的子字符串,返回 true;如果不存在,返回 false 。

bool isSubstringPresent(char* s) {
    int len = strlen(s);
    for (int i = 0; i < len - 1; i++) {
        char substr[3] = {s[i + 1], s[i], '\0'};
        if (strstr(s, substr)) {
            return true;
        }
    }
    return false;
}

按键变更的次数

按键变更的次数https://leetcode.cn/problems/number-of-changing-keys/

给你一个下标从 0 开始的字符串 s ,该字符串由用户输入。按键变更的定义是:使用与上次使用的按键不同的键。例如 s = "ab" 表示按键变更一次,而 s = "bBBb" 不存在按键变更。

返回用户输入过程中按键变更的次数。

注意:shift 或 caps lock 等修饰键不计入按键变更,也就是说,如果用户先输入字母 'a' 然后输入字母 'A' ,不算作按键变更。

int countKeyChanges(char* s) {
    
    int ans = 0;
    for(int i = 0;i < strlen(s);i ++){
        if(abs(s[i  + 1] - s[i]) != 0 && abs(s[i + 1] - s[i]) != 32){
            ans ++;
        }
    }
    return ans - 1;
}


长度为K的子数组的能量值

长度为 K 的子数组的能量值 IIhttps://leetcode.cn/problems/find-the-power-of-k-size-subarrays-ii/

给你一个长度为 n 的整数数组 nums 和一个正整数 k 。

一个数组的 能量值 定义为:

  • 如果 所有 元素都是依次 连续(即 nums[i] + 1 = nums[i + 1]i < n)且 上升 的,那么能量值为 最大 的元素。
  • 否则为 -1 。

你需要求出 nums 中所有长度为 k 的 子数组 的能量值。

请你返回一个长度为 n - k + 1 的整数数组 results ,其中 results[i] 是子数组 nums[i..(i + k - 1)] 的能量值。

int* resultsArray(int* nums, int numsSize, int k, int* returnSize) {
    *returnSize = numsSize - k + 1;
    int* ans = (int*)malloc((*returnSize) * sizeof(int));
    int cnt = 0;
    for (int i = 0; i < *returnSize; i++) {
        ans[i] = -1;
    }
    for (int i = 0; i < numsSize; i++) {
        cnt = (i == 0 || nums[i] - nums[i - 1] != 1) ? 1 : cnt + 1;
        if (cnt >= k) {
            ans[i - k + 1] = nums[i];
        }
    }
    return ans;
}

第二天

对角线上不同值的数量查

对角线上不同值的数量差https://leetcode.cn/problems/difference-of-number-of-distinct-values-on-diagonals/

给你一个下标从 0 开始、大小为 m x n 的二维矩阵 grid ,请你求解大小同样为 m x n 的答案矩阵 answer 。

矩阵 answer 中每个单元格 (r, c) 的值可以按下述方式进行计算:

  • 令 topLeft[r][c] 为矩阵 grid 中单元格 (r, c) 左上角对角线上 不同值 的数量。
  • 令 bottomRight[r][c] 为矩阵 grid 中单元格 (r, c) 右下角对角线上 不同值 的数量。

然后 answer[r][c] = |topLeft[r][c] - bottomRight[r][c]| 。

返回矩阵 answer 。

矩阵对角线 是从最顶行或最左列的某个单元格开始,向右下方向走到矩阵末尾的对角线。

如果单元格 (r1, c1) 和单元格 (r, c) 属于同一条对角线且 r1 < r ,则单元格 (r1, c1) 属于单元格 (r, c) 的左上对角线。类似地,可以定义右下对角线。

class Solution(object):
    def differenceOfDistinctValues(self, grid):
        """
        :type grid: List[List[int]]
        :rtype: List[List[int]]
        """
        m,n=len(grid),len(grid[0])
        ans=[[0]*n for _ in range(m)]
        st=set()
        for i in range(m):
            for j in range(n):
                st.clear()
                x,y=i-1,j-1
                while x>=0 and y>=0:
                    st.add(grid[x][y])
                    x-=1
                    y-=1
                top_left=len(st)
                st.clear()
                x,y=i+1,j+1
                while x

区间加法

区间加法 IIhttps://leetcode.cn/problems/range-addition-ii/

给你一个 m x n 的矩阵 M 和一个操作数组 op 。矩阵初始化时所有的单元格都为 0 。ops[i] = [ai, bi] 意味着当所有的 0 <= x < ai 和 0 <= y < bi 时, M[x][y] 应该加 1。

在 执行完所有操作后 ,计算并返回 矩阵中最大整数的个数 。

#include 

int maxCount(int m, int n, int** ops, int opsSize, int* opsColSize) {
    // 初始化最小行和最小列
    int minRow = m;
    int minCol = n;

    // 遍历所有操作
    for (int i = 0; i < opsSize; i++) {
        int row = ops[i][0];
        int col = ops[i][1];
        // 更新最小行
        if (row < minRow) {
            minRow = row;
        }
        // 更新最小列
        if (col < minCol) {
            minCol = col;
        }
    }

    // 返回最大数值元素的数量
    return minRow * minCol;
}

交换后字典序最小的字符串

交换后字典序最小的字符串https://leetcode.cn/problems/lexicographically-smallest-string-after-a-swap/

给你一个仅由数字组成的字符串 s,在最多交换一次 相邻 且具有相同 奇偶性 的数字后,返回可以得到的字典序最小的字符串。

如果两个数字都是奇数或都是偶数,则它们具有相同的奇偶性。例如,5 和 9、2 和 4 奇偶性相同,而 6 和 9 奇偶性不同。

char* getSmallestString(char* s) {
    int len = strlen(s);
    for (int i = 0; i + 1 < len; i++) {
        // 如果相邻字符满足条件,交换它们的位置
        if (s[i] > s[i + 1] && (s[i] % 2 == s[i + 1] % 2)) {
            char tmp = s[i];
            s[i] = s[i + 1];
            s[i + 1] = tmp;
            break;
        }
    }
    return s;
}

第三天

使所有字符相等的最小成本

使所有字符相等的最小成本https://leetcode.cn/problems/minimum-cost-to-make-all-characters-equal/

给你一个下标从 0 开始、长度为 n 的二进制字符串 s ,你可以对其执行两种操作:

  • 选中一个下标 i 并且反转从下标 0 到下标 i(包括下标 0 和下标 i )的所有字符,成本为 i + 1 。
  • 选中一个下标 i 并且反转从下标 i 到下标 n - 1(包括下标 i 和下标 n - 1 )的所有字符,成本为 n - i 。

返回使字符串内所有字符 相等 需要的 最小成本 。

反转 字符意味着:如果原来的值是 '0' ,则反转后值变为 '1' ,反之亦然。

long long minimumCost(char* s) {
    int n = strlen(s);
    long long suf[n + 1][2];
    memset(suf, 0, sizeof(suf));
    for (int i = n - 1; i >= 0; i--) {
        if (s[i] == '1') {
            suf[i][1] = suf[i + 1][1];
            suf[i][0] = suf[i + 1][1] + (n - i);
        } else {
            suf[i][1] = suf[i + 1][0] + (n - i);
            suf[i][0] = suf[i + 1][0];
        }
    }

    long long pre[2] = {0, 0};
    long long res = LLONG_MAX;
    for (int i = 0; i < n; i++) {
        if (s[i] == '1') {
            pre[0] = pre[1] + i + 1;
        } else {
            pre[1] = pre[0] + i + 1;
        }
        res = fmin(res, fmin(pre[0] + suf[i + 1][0], pre[1] + suf[i + 1][1]));
    }
    return res;
}

第四天

统计重新排列后包含另一个字符串的字符串数目

统计重新排列后包含另一个字符串的子字符串数目 Ihttps://leetcode.cn/problems/count-substrings-that-can-be-rearranged-to-contain-a-string-i/

给你两个字符串 word1 和 word2 。

如果一个字符串 x 重新排列后,word2 是重排字符串的 前缀 ,那么我们称字符串 x 是 合法的 。

请你返回 word1 中 合法 子字符串 的数目。

int get(int l, int r, int preCount[][26], int* count) {
    int border = l;
    while (l < r) {
        int m = (l + r) >> 1;
        int f = 1;
        for (int i = 0; i < 26; i++) {
            if (preCount[m][i] - preCount[border - 1][i] < count[i]) {
                f = 0;
                break;
            }
        }
        if (f) {
            r = m;
        } else {
            l = m + 1;
        }
    }
    return l;
}

long long validSubstringCount(char* word1, char* word2) {
    int count[26] = {0};
    for (int i = 0; word2[i]; i++) {
        count[word2[i] - 'a']++;
    }

    int n = strlen(word1);
    int preCount[n + 1][26];
    memset(preCount, 0, sizeof(preCount));
    for (int i = 1; i <= n; i++) {
        memcpy(preCount[i], preCount[i - 1], sizeof(preCount[i]));
        preCount[i][word1[i - 1] - 'a']++;
    }

    long long res = 0;
    for (int l = 1; l <= n; l++) {
        int r = get(l, n + 1, preCount, count);
        res += n - r + 1;
    }
    return res;
}

统计数组中相等且可以被整除的数对

统计数组中相等且可以被整除的数对https://leetcode.cn/problems/count-equal-and-divisible-pairs-in-an-array/

给你一个下标从 0 开始长度为 n 的整数数组 nums 和一个整数 k ,请你返回满足 0 <= i < j < n ,nums[i] == nums[j] 且 (i * j) 能被 k 整除的数对 (i, j) 的 数目 。

int countPairs(int* nums, int numsSize, int k) {
    
    int ans = 0;
    for(int i = 0;i < numsSize;i++){
        for(int j = i + 1;j < numsSize;j++){
            if(nums[i] == nums[j]){
                if((i*j)%k == 0){
                    ans ++;
                }
            }
        }
    }
    return ans;
}

第五天

统计好三元组

统计好三元组https://leetcode.cn/problems/count-good-triplets/

给你一个整数数组 arr ,以及 ab 、c 三个整数。请你统计其中好三元组的数量。

如果三元组 (arr[i], arr[j], arr[k]) 满足下列全部条件,则认为它是一个 好三元组 。

  • 0 <= i < j < k < arr.length
  • |arr[i] - arr[j]| <= a
  • |arr[j] - arr[k]| <= b
  • |arr[i] - arr[k]| <= c

其中 |x| 表示 x 的绝对值。

返回 好三元组的数量 。

int countGoodTriplets(int* arr, int arrSize, int a, int b, int c) {
    int cnt = 0;
    for (int i = 0; i < arrSize; ++i) {
        for (int j = i + 1; j < arrSize; ++j) {
            for (int k = j + 1; k < arrSize; ++k) {
                if (abs(arr[i] - arr[j]) <= a && abs(arr[j] - arr[k]) <= b && abs(arr[i] - arr[k]) <= c) {
                    ++cnt;
                }
            }
        }
    }
    return cnt;
}

L1-003 个位数统计

给定一个 k 位整数 N=dk−1​10k−1+⋯+d1​101+d0​ (0≤di​≤9, i=0,⋯,k−1, dk−1​>0),请编写程序统计每种不同的个位数字出现的次数。例如:给定 N=100311,则有 2 个 0,3 个 1,和 1 个 3。

输入格式:

每个输入包含 1 个测试用例,即一个不超过 1000 位的正整数 N。

输出格式:

对 N 中每一种不同的个位数字,以 D:M 的格式在一行中输出该位数字 D 及其在 N 中出现的次数 M。要求按 D 的升序输出。

#include 

using namespace std;

int main(){

    string input;
    cin >> input;

    int arr[10] = {0};
    for(int i = 0;i < input.size();i ++){
        arr[input[i] - '0'] ++;
    }

     for(int i = 0;i < 10;i ++){
        if(arr[i] != 0){
            cout << i << ":" << arr[i] << endl;
        }
    }
    
    return 0;
}

 第六天

L1-090 什么是机器学习

面试官:9 + 10 等于多少?
答:3
面试官:差远了,是19。
答:16
面试官:错了,是19。
答:18
面试官:不,是19。
答:19

本题就请你模仿这个“机器学习程序”的行为。

输入格式:

输入在一行中给出两个整数,绝对值都不超过 100,中间用一个空格分开,分别表示面试官给出的两个数字 A 和 B。

输出格式:

要求你输出 4 行,每行一个数字。第 1 行比正确结果少 16,第 2 行少 3,第 3 行少 1,最后一行才输出 A+B 的正确结果。

输入样例:

9 10

输出样例:

3
16
18
19
# include 

using namespace std;

int main(){

    int N,M;
    cin >> N >> M;

    int ans = N + M;

    cout << ans - 16 << endl;
    cout << ans - 3 << endl;
    cout << ans - 1 << endl;
    cout << ans;
    
    return 0;
}

L1-081 今天我要赢

2018 年我们曾经出过一题,是输出“2018 我们要赢”。今年是 2022 年,你要输出的句子变成了“我要赢!就在今天!”然后以比赛当天的日期落款。

输入格式:

本题没有输入。

输出格式:

输出分 2 行。在第一行中输出 I'm gonna win! Today!,在第二行中用 年年年年-月月-日日 的格式输出比赛当天的日期。已知比赛的前一天是 2022-04-22

#include 

using namespace std;

int main(){

    cout << "I'm gonna win! Today!" << endl;
    cout << "2022-04-23";

    return 0;
}

L1-053 电子汪

据说汪星人的智商能达到人类 4 岁儿童的水平,更有些聪明汪会做加法计算。比如你在地上放两堆小球,分别有 1 只球和 2 只球,聪明汪就会用“汪!汪!汪!”表示 1 加 2 的结果是 3。

本题要求你为电子宠物汪做一个模拟程序,根据电子眼识别出的两堆小球的个数,计算出和,并且用汪星人的叫声给出答案。

输入格式:

输入在一行中给出两个 [1, 9] 区间内的正整数 A 和 B,用空格分隔。

输出格式:

在一行中输出 A + B 个Wang!

输入样例:

2 1

输出样例:

Wang!Wang!Wang!
#include 

using namespace std;

int main(){

    int N,M;
    cin >> N >> M;

    for(int i =0;i < N+M;i++){
        cout << "Wang!";
    }
     cout << endl;
    return 0;
}

第七天

L1-073 人与神

跨界大神 L. Peter Deutsch 有一句名言:“To iterate is human, to recurse divine.”(迭代的是人,递归的是神)。本题就请你直接在屏幕上输出这句话。

输入格式:

本题没有输入。

输出格式:

在一行中输出 To iterate is human, to recurse divine.

#include 

using namespace std;

int main(){
    cout << "To iterate is human, to recurse divine." << endl;
    return 0;
}


L1-102 兰州牛肉面

兰州牛肉面是历史悠久的美食,根据牛肉面的宽窄、配料的种类,可以细分为上百个不同的品种。你进到兰州的任何一家牛肉面馆,只说:“来一碗牛肉面!”就好像进到加州的咖啡馆说“来一杯咖啡”一样,会被店主人当成外星人……
本题的任务是,请你写程序帮助一家牛肉面馆的老板统计一下,他们一天卖出各种品种的牛肉面有多少碗,营业额一共有多少。

输入格式:

输入第一行给出一个正整数 N(≤100),为牛肉面的种类数量。这里为了简单起见,我们把不同种类的牛肉面从 1 到 N 编号,以后就用编号代替牛肉面品种的名称。第二行给出 N 个价格,第 i 个价格对应第 i 种牛肉面一碗的单价。这里的价格是 [0.01, 200.00] 区间内的实数,以元为单位,精确到分。
随后是一天内客人买面的记录,每条记录占一行,格式为:

品种编号 碗数

其中碗数保证是正整数。当对应的 品种编号0 时,表示输入结束。这个记录不算在内。

输出格式:

首先输出 N 行,第 i 行输出第 i 种牛肉面卖出了多少碗。最后一行输出当天的总营业额,仍然是以元为单位,精确到分。题目保证总营业额不超过 106。

输入样例:

#include 

int main() {
    int N;
    std::cin >> N;

    std::vector prices(N);
    std::vector sales(N, 0);
    double total_income = 0.0;

    // 读取每种牛肉面的单价
    for (int i = 0; i < N; ++i) {
        std::cin >> prices[i];
    }

    int variety, bowls;
    while (true) {
        std::cin >> variety >> bowls;
        if (variety == 0) {
            break;
        }
        // 确保品种编号在有效范围内
        if (variety >= 1 && variety <= N) {
            sales[variety - 1] += bowls;
            total_income += prices[variety - 1] * bowls;
        }
    }

    // 输出每种牛肉面的销售数量
    for (int i = 0; i < N; ++i) {
        std::cout << sales[i] << std::endl;
    }

    // 输出总营业额,精确到分
    std::cout << std::fixed << std::setprecision(2) << total_income << std::endl;

    return 0;
} 

L1-041 寻找250

对方不想和你说话,并向你扔了一串数…… 而你必须从这一串数字中找到“250”这个高大上的感人数字。

输入格式:

输入在一行中给出不知道多少个绝对值不超过1000的整数,其中保证至少存在一个“250”。

输出格式:

在一行中输出第一次出现的“250”是对方扔过来的第几个数字(计数从1开始)。题目保证输出的数字在整型范围内。

输入样例:

888 666 123 -233 250 13 250 -222

输出样例:

5
#include 

using namespace std;

int main(){
    int n = 0;
    int w;
    while(1){
        cin >> w;
        if(w ==250){
            cout << n + 1 << endl;
            break;
        }else{
             n ++;
        }
    }
    return 0;
}

总结

近期有项目耽搁了几天刷题 然后为了准备天梯赛和蓝桥 选择性的刷了一些PTA和蓝桥的题

你可能感兴趣的:(算法日常刷题笔记(7))