start至finish,每个数位不超过limit,数的后缀为s

文章介绍了如何解决LeetCode中一道关于计数特定范围内数字的问题,涉及到数位限制和后缀条件。作者提供了一个Solution类的代码片段,通过拆分数字和比较数位来计算符合条件的数的数量。

leetcode双周赛121最后一题,错了好多次,有点扣脚,记个自己的模板。

题目描述

从start至finish,每个数位都不能超过limit,且数的后缀为s(保证s的每个数位都不超过limit),求一共有多少个这样的数。

大致思路:

只要求出0~finish 有符合要求的数以及0~start-1有多少这样的数,然后减一减就行了,具体怎么算,详情看代码。

代码如下:

using ll = long long;
class Solution {
private:
    int limit;
    long long countIt(long long x, string s)
    {
        // 将x做拆分
        vector<int> arr;
        while (x > 0)
        {
            arr.push_back(x % 10);
            x /= 10;
        }
        // 如果x的长度比s还小,直接返回0
        if (arr.size() < s.size()) return 0;

        int n = arr.size(), m = s.size();
        ll ans = 0;
        for (int i = n - 1; i >= 0; --i)
        {
            if (i + 1 > m)
            {
                // 位数大于后缀长度时
                if (arr[i] == limit)
                {
                    //如果当前位等于limit,那么当前位为0~limit-1时,后置位可以只在limit的限制下取,limit后置位有i - m位,个数即为pow(limit + 1, i - m),再乘以limit;当前位为limit时,继续看下一位。
                    ans += pow(limit + 1, i - m) * limit;
                }
                else if (arr[i] < limit)
                {
                    // 如果当前位小于limit,那么当前位为0~arr[i] - 1时可以为所欲为;当前位为arr[i]时,继续看下一位。
                    ans += pow(limit + 1, i - m) * arr[i];
                }
                else if (arr[i] > limit)
                {
                    // 如果大于limit,那么当前位为0~limit都可以为所欲为,剩下的不用看了
                    ans += pow(limit + 1, i + 1 - m);
                    break;
                }
            }
            else 
            {
                // 位数小于等于后缀长度时
                if (arr[i] > s[m - 1 - i] - '0')
                {
                    // 当前位大于后缀的当前位,那么后缀必定可以取到+1,退出循环
                    ans += 1;
                    break;
                }
                else if (arr[i] == s[m - 1 - i] - '0')
                {
                    // 当前位等于后缀的当前位,如果已经是个位时+1,否则继续看下一位
                    if (i == 0)
                    {
                        ans += 1;
                    }
                }
                else if (arr[i] < s[m - 1 - i] - '0')
                {
                    // 当前位小于后缀的当前位,那么必取不到后缀了,退出循环
                    break;
                }
            }
        }
        return ans;
    }
public:
    long long numberOfPowerfulInt(long long start, long long finish, int limit, string s) {
        this->limit = limit;
        return countIt(finish, s) - countIt(start - 1, s);
    }
};

以下代码存在段错误,分析原因 /* 当前方案使用软件方案将yuv据缩放到目标尺寸 */ static void scale_yuv420_bilinear(unsigned char *src, int src_w, int src_h, unsigned char *dst, int dst_w, int dst_h) { // 提取源YUV平面指针 unsigned char *src_y = src; unsigned char *src_u = src + src_w * src_h; unsigned char *src_v = src_u + (src_w/2) * (src_h/2); // 提取目标YUV平面指针 unsigned char *dst_y = dst; unsigned char *dst_u = dst + dst_w * dst_h; unsigned char *dst_v = dst_u + (dst_w/2) * (dst_h/2); // 缩放Y平面(全分辨率) for (int j = 0; j < dst_h; j++) { float y_ratio = (float)j / dst_h * src_h; int y_idx = (int)y_ratio; float y_fraction = y_ratio - y_idx; for (int i = 0; i < dst_w; i++) { float x_ratio = (float)i / dst_w * src_w; int x_idx = (int)x_ratio; float x_fraction = x_ratio - x_idx; // 双线性插值计算 float y00 = src_y[y_idx * src_w + x_idx]; float y01 = src_y[y_idx * src_w + (x_idx + 1 < src_w ? x_idx + 1 : x_idx)]; float y10 = src_y[(y_idx + 1 < src_h ? y_idx + 1 : y_idx) * src_w + x_idx]; float y11 = src_y[(y_idx + 1 < src_h ? y_idx + 1 : y_idx) * src_w + (x_idx + 1 < src_w ? x_idx + 1 : x_idx)]; float interpolated = y00 * (1 - x_fraction) * (1 - y_fraction) + y01 * x_fraction * (1 - y_fraction) + y10 * (1 - x_fraction) * y_fraction + y11 * x_fraction * y_fraction; dst_y[j * dst_w + i] = (unsigned char)interpolated; } } // 缩放U和V平面(半分辨率,方法类似) int src_u_w = src_w / 2, src_u_h = src_h / 2; int dst_u_w = dst_w / 2, dst_u_h = dst_h / 2; for (int j = 0; j < dst_u_h; j++) { float y_ratio = (float)j / dst_u_h * src_u_h; int y_idx = (int)y_ratio; float y_fraction = y_ratio - y_idx; for (int i = 0; i < dst_u_w; i++) { float x_ratio = (float)i / dst_u_w * src_u_w; int x_idx = (int)x_ratio; float x_fraction = x_ratio - x_idx; // U平面双线性插值 float u00 = src_u[y_idx * src_u_w + x_idx]; float u01 = src_u[y_idx * src_u_w + (x_idx + 1 < src_u_w ? x_idx + 1 : x_idx)]; float u10 = src_u[(y_idx + 1 < src_u_h ? y_idx + 1 : y_idx) * src_u_w + x_idx]; float u11 = src_u[(y_idx + 1 < src_u_h ? y_idx + 1 : y_idx) * src_u_w + (x_idx + 1 < src_u_w ? x_idx + 1 : x_idx)]; float u_interp = u00 * (1 - x_fraction) * (1 - y_fraction) + u01 * x_fraction * (1 - y_fraction) + u10 * (1 - x_fraction) * y_fraction + u11 * x_fraction * y_fraction; dst_u[j * dst_u_w + i] = (unsigned char)u_interp; // V平面同样处理 float v00 = src_v[y_idx * src_u_w + x_idx]; float v01 = src_v[y_idx * src_u_w + (x_idx + 1 < src_u_w ? x_idx + 1 : x_idx)]; float v10 = src_v[(y_idx + 1 < src_u_h ? y_idx + 1 : y_idx) * src_u_w + x_idx]; float v11 = src_v[(y_idx + 1 < src_u_h ? y_idx + 1 : y_idx) * src_u_w + (x_idx + 1 < src_u_w ? x_idx + 1 : x_idx)]; float v_interp = v00 * (1 - x_fraction) * (1 - y_fraction) + v01 * x_fraction * (1 - y_fraction) + v10 * (1 - x_fraction) * y_fraction + v11 * x_fraction * y_fraction; dst_v[j * dst_u_w + i] = (unsigned char)v_interp; } } } /* 自定义内存目标管理器结构体 */ struct jpeg_mem_dest_mgr { struct jpeg_destination_mgr pub; /* 公共字段 */ JOCTET *buffer; /* 内存缓冲区指针 */ size_t bufsize; /* 缓冲区总大小 */ size_t datasize; /* 已写入据大小 */ }; static char* convert_fileid_to_filename(const char* file_id) { // 检查输入合法性 if (file_id == NULL) { DBPRINTF(DEBUG_LEVEL_ERROR, "illegal file_id: NULL\n"); return NULL; } if (strlen(file_id) != 14) { DBPRINTF(DEBUG_LEVEL_ERROR, "file_id length must be 14, got %zu\n", strlen(file_id)); return NULL; } // 提取前两位作为快照类型字符串("00"/"01"/"02") char type_str[3]; strncpy(type_str, file_id, 2); type_str[2] = '\0'; // 确保字符串终止符 int snapshot_type = atoi(type_str); // 根据类型确定基础路径 const char* base_path = NULL; switch (snapshot_type) { case PTZ_SNAPSHOT_PRESET: // "00"对应预设路径 base_path = PRESET_SNAPSHOT_PATH; break; case PTZ_SNAPSHOT_LIMIT: // "01"对应限制路径 base_path = LIMIT_SANPSHOT_PATH; break; case PTZ_SNAPSHOT_HOME: // "02"对应主页路径 base_path = HOME_SNAPSHOT_PATH; break; default: DBPRINTF(DEBUG_LEVEL_ERROR, "invalid snapshot_type: %s\n", type_str); return NULL; } // 提取最后5位作为文件ID后缀(14位字符串中索引9-13为最后5位) const char* file_id_suffix = file_id + 9; // 动态分配文件名缓冲区(避免返回局部变量) char* file_name = (char*)malloc(256); if (file_name == NULL) { DBPRINTF(DEBUG_LEVEL_ERROR, "malloc failed for filename buffer\n"); return NULL; } // 拼接完整文件路径 snprintf(file_name, 256, "%s/%s.jpeg", base_path, file_id_suffix); return file_name; } S32 ptz_snapshot(const char* file_id, int dst_width, int dst_height) { int ret = -1; S32 src_width = -1; S32 src_height = -1; S32 yuv_size = 0; U8 *yuvBuf = NULL; /* libjpeg变量声明 */ struct jpeg_compress_struct cinfo; struct jpeg_error_mgr jerr; JSAMPROW y_plane[160], cb_plane[80], cr_plane[80]; /* 扫描线指针组 */ JSAMPARRAY image_data[3] = { y_plane, cb_plane, cr_plane }; /* 分量据指针 */ size_t final_jpeg_size = 0; int quality = 95; /* 初始质量因子 */ size_t target_jpeg_size = 10 * 1024; int retry_count = 3; char *filename = NULL; filename = convert_fileid_to_filename(file_id); size_t items_written = 0; if (NULL == file_id) { DBPRINTF(DEBUG_LEVEL_ERROR, "preset_snap path or name is NULL\n"); return ret; } yuv_size = avdc_get_minor_yuv(&yuvBuf, &src_width, &src_height); if(yuv_size < 0 || src_width < 0 || src_height < 0) { DBPRINTF(DEBUG_LEVEL_ERROR, "get minor yuv failed\n"); return ret; } DBPRINTF(DEBUG_LEVEL_ERROR, "get minor yuv success\n"); U8* scaled_yuv = (U8*)malloc(src_width * src_height * 1.5); if(scaled_yuv == NULL) { DBPRINTF(DEBUG_LEVEL_ERROR, "malloc error\n"); return ret; } scale_yuv420_bilinear(yuvBuf, src_width, src_height, scaled_yuv, dst_width, dst_height); DBPRINTF(DEBUG_LEVEL_ERROR, "scale success\n"); /* 分配JPEG输出缓冲区(初始20KB) */ size_t jpeg_buf_size = 20 * 1024; unsigned char *jpeg_buffer = (unsigned char *)malloc(jpeg_buf_size); if (jpeg_buffer == NULL) { DBPRINTF(DEBUG_LEVEL_ERROR, "malloc for jpeg_buffer failed\n"); free(scaled_yuv); return ret; } /* 初始化JPEG压缩对象 */ cinfo.err = jpeg_std_error(&jerr); jpeg_create_compress(&cinfo); jpeg_mem_dest(&cinfo, &jpeg_buffer, &jpeg_buf_size); /* 设置内存目标 */ /* 设置图像参 */ cinfo.image_width = dst_width; /* 宽度200 */ cinfo.image_height = dst_height; /* 高度160 */ cinfo.input_components = 3; /* 3个分量(Y、Cb、Cr) */ cinfo.in_color_space = JCS_YCbCr; /* 直接使用YCbCr颜色空间 */ /* 设置采样因子(YUV420对应4:2:0) */ cinfo.comp_info[0].h_samp_factor = 2; /* Y水平采样因子2 */ cinfo.comp_info[0].v_samp_factor = 2; /* Y垂直采样因子2 */ cinfo.comp_info[1].h_samp_factor = 1; /* Cb水平采样因子1 */ cinfo.comp_info[1].v_samp_factor = 1; /* Cb垂直采样因子1 */ cinfo.comp_info[2].h_samp_factor = 1; /* Cr水平采样因子1 */ cinfo.comp_info[2].v_samp_factor = 1; /* Cr垂直采样因子1 */ jpeg_set_defaults(&cinfo); cinfo.raw_data_in = TRUE; /* 启用原始据输入模式,避免中间转换 */ /* 填充扫描线指针组 */ for (int i = 0; i < dst_height; i++) { y_plane[i] = &scaled_yuv[i * dst_width]; /* Y分量每行200字节 */ } for (int i = 0; i < dst_height / 2; i++) { cb_plane[i] = &scaled_yuv[dst_width * dst_height + i * (dst_width / 2)]; /* Cb分量每行100字节 */ cr_plane[i] = &scaled_yuv[dst_width * dst_height + (dst_width / 2) * (dst_height / 2) + i * (dst_width / 2)]; /* Cr分量每行100字节 */ } /* 质量控制循环:do-while调整质量直至JPEG大小<10KB */ do { jpeg_set_quality(&cinfo, quality, TRUE); /* 设置质量因子 */ jpeg_start_compress(&cinfo, TRUE); /* 写入原始据(避免YUV420到YUV444转换) */ while (cinfo.next_scanline < cinfo.image_height) { int mcu_height = cinfo.max_v_samp_factor * DCTSIZE; /* MCU高度=16像素 */ int rows_to_write = (cinfo.image_height - cinfo.next_scanline) < mcu_height ? (cinfo.image_height - cinfo.next_scanline) : mcu_height; jpeg_write_raw_data(&cinfo, image_data, rows_to_write); /* 更新指针到下一行 */ for (int i = 0; i < rows_to_write; i++) { y_plane[i] += dst_width; /* Y指针后移一行 */ } for (int i = 0; i < rows_to_write / 2; i++) { cb_plane[i] += (dst_width / 2); /* Cb指针后移半行 */ cr_plane[i] += (dst_width / 2); /* Cr指针后移半行 */ } } jpeg_finish_compress(&cinfo); final_jpeg_size = ((struct jpeg_mem_dest_mgr *)cinfo.dest)->datasize; quality -= 2; /* 满足条件,降低质量 */ if (quality <= 0) { DBPRINTF(DEBUG_LEVEL_ERROR, "Unable to compress image below 10KB even at lowest quality\n"); break; } } while (final_jpeg_size < target_jpeg_size); FILE *fp = fopen(filename, "wb"); if (fp) { /* 提供写入失败处理逻辑,写入失败则丢弃当前缓冲区据并重试指定次 */ while(retry_count) { items_written = fwrite(jpeg_buffer, 1, final_jpeg_size, fp); if(items_written == final_jpeg_size) { DBPRINTF(DEBUG_LEVEL_ERROR, "success to write %s\n", filename); fclose(fp); ret = 0; /* 成功 */ goto release_data; } else { retry_count--; DBPRINTF(DEBUG_LEVEL_ERROR, "failed to write %s, retry_count %d\n", filename, retry_count); if (fflush(fp) != 0) { DBPRINTF(DEBUG_LEVEL_ERROR, "failed to fflush\n"); } clearerr(fp); } } if (0 == retry_count) { DBPRINTF(DEBUG_LEVEL_ERROR, "retry_count come limit, failed to write!\n"); } fclose(fp); } else { DBPRINTF(DEBUG_LEVEL_ERROR, "Failed to open file for writing: %s\n", filename); } release_data: jpeg_destroy_compress(&cinfo); free(filename); free(jpeg_buffer); free(scaled_yuv); return ret; }
11-22
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值