CCF 202104-1 灰度直方图 和 LeetCode 93 复原IP地址

CCF 202104-1 灰度直方图

在这里插入图片描述
在这里插入图片描述

思路:

图像识别中经常用到像素矩阵问题,如卷积神经网络的卷积操作,注意像素的范围即ASCII范围0-255之间。本题目描述复杂(ccf一贯作风)但是核心其实是在统计:输入n行m列个元素,且元素范围位于0到L-1之间的整数,即[0,L),每个元素出现的次数。即输出为L个数据。

代码实现

#include <iostream>
#include <cstring>
#include <algorithm>
using namespace std;
const int N = 260;
int n, m, L;
int s[N];//定义最多含有260个元素的数组,4<=L<=256
int main()
{
    scanf_s("%d%d%d", &n, &m, &L);//输入行数列数及多少元素
    for (int i = 0; i < n; i++)
        for (int j = 0; j < m; j++)
        {
            int x;
            scanf_s("%d", &x);//依次输入每行每列的元素值
            s[x] ++;//累计计算当前输入元素的出现次数
        }
    for (int i = 0; i < L; i++)
        printf("%d ", s[i]);//输出所有元素出现的次数
    return 0;
}

LeetCode 93 复原IP地址

在这里插入图片描述
在这里插入图片描述

思路

注意:回溯是一种算法思想,可以用递归实现,基本是相辅相成的,回溯函数或者递归函数其实都可以。本题属于海大计算机技术考纲中递归和递推问题,可以解决字符串切割、回文子串等关于字符串的问题,当然递归也可以解决多种问题,如2020年考察的八皇后问题等。
题目给定的就是一个字符串,切割成4块,判定是不是符合ip地址,那么可以使用递归来实现。通过下图可以看出当我们开始切割至最后我们一直在判断当前切割的字符是不是符合ip地址,直到切割成4块,即一条道走到黑,那么可以使用DFS(深度优先搜索)的思想。
在这里插入图片描述

代码实现

class Solution {
private:
    vector<string> result;// 记录结果
    // startIndex: 搜索的起始位置,pointNum:添加逗点的数量
    void backtracking(string& s, int startIndex, int pointNum) {
        if (pointNum == 3) { // 逗点数量为3时,分隔结束
            // 判断第四段子字符串是否合法,如果合法就放进result中
            if (isValid(s, startIndex, s.size() - 1)) {
                result.push_back(s);
            }
            return;
        }
        for (int i = startIndex; i < s.size(); i++) {
            if (isValid(s, startIndex, i)) { // 判断 [startIndex,i] 这个区间的子串是否合法
                s.insert(s.begin() + i + 1 , '.');  // 在i的后面插入一个逗点
                pointNum++;
                backtracking(s, i + 2, pointNum);   // 插入逗点之后下一个子串的起始位置为i+2
                pointNum--;                         // 回溯
                s.erase(s.begin() + i + 1);         // 回溯删掉逗点
            } else break; // 不合法,直接结束本层循环
        }
    }
    // 判断字符串s在左闭右闭区间[start, end]所组成的数字是否合法
    bool isValid(const string& s, int start, int end) {
        if (start > end) {
            return false;
        }
        if (s[start] == '0' && start != end) { // 0开头的数字不合法
                return false;
        }
        int num = 0;
        for (int i = start; i <= end; i++) {
            if (s[i] > '9' || s[i] < '0') { // 遇到非数字字符不合法
                return false;
            }
            num = num * 10 + (s[i] - '0');
            if (num > 255) { // 如果大于255了不合法
                return false;
            }
        }
        return true;
    }
public:
    vector<string> restoreIpAddresses(string s) {
        result.clear();
        if (s.size() > 12) return result; // 算是剪枝了
        backtracking(s, 0, 0);
        return result;
    }
};

当然还有一种最原始的暴力破解方式,直接把4中分割情况用四重循环表示出来,每一重检查当前字符块是不是符合ip地址要求:

class Solution {
public:
    vector<string> restoreIpAddresses(string s) {
        vector<string> res;

        for (int a = 1; a < 4; a ++ )
            for (int b = 1; b < 4; b ++ )
                for (int c = 1; c < 4; c ++ )
                    for (int d = 1; d < 4; d ++ )           //abcd分别表示四段ip地址长度
                    {
                        if (a + b + c + d == s.size())      //四段长度刚好
                        {
                            string s1 = s.substr(0, a);     //分别截取四段ip地址
                            string s2 = s.substr(a, b);
                            string s3 = s.substr(a + b, c);
                            string s4 = s.substr(a + b + c);

                            if (check(s1) && check(s2) && check(s3) && check(s4))
                            {
                                string ip = s1 + '.' + s2 + '.' + s3 + '.' + s4;
                                res.push_back(ip);
                            }
                        }
                    }

        return res;
    }

    bool check(string s)        //判断ip地址每段的第一位不为0,或只有一位且该位为0
    {
        if (stoi(s) <= 255)
            if (s[0] != '0' || (s[0] == '0' && s.size() == 1)) return true;
        
        return false;
    }
};

本图文内容来源于网友网络收集整理提供,作为学习参考使用,版权属于原作者。
THE END
分享
二维码
< <上一篇
下一篇>>