3.Digit Counts-统计数字(中等题)

本文介绍了一种通过编程方式计算指定数字k在0至n范围内的整数中出现次数的方法。采用逐个检查的方式进行统计,并提供了一个具体的示例,即在0至12范围内数字1出现的次数。

统计数字

  1. 题目

    计算数字k在0到n中的出现的次数,k可能是0~9的一个值

  2. 样例

    例如n=12,k=1,在 [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12],我们发现1出现了5次 (1, 10, 11, 12)

  3. 题解

只想到了暴力枚举,如有更好的办法还望告知。

class Solution {
    /*
     * param k : As description.
     * param n : As description.
     * return: An integer denote the count of digit k in 1..n
     */
    public int digitCounts(int k, int n) {
        int count = 0;
        for (int i=0;i<=n;i++)
        {
            count+=getCount(i,k);
        }

        return count;
    }

    private int getCount(int n,int k)
    {
        int result = 0;
        if (n==0 && k==0)
        {
            return 1;
        }
        while (n != 0)
        {
            if (n % 10 == k)
            {
                result++;
            }
            n /=10;
        }
        return result;
    }
};

Last Update 2016.9.18

function dtmf_phone_recognition_improved() % 改进的DTMF电话号码识别系统 % 能够抵抗不同程度的高斯白噪声干扰 % 参数设置 Fs = 44100; % 采样率 tone_duration = 0.1; % 每个音调持续时间() pause_duration = 0.05; % 音调间隔时间() % DTMF频率定义 low_freqs = [697, 770, 852, 941]; % 低频组 high_freqs = [1209, 1336, 1477, 1633]; % 高频组 % DTMF键盘映射 dtmf_keys = [ &#39;1&#39;, &#39;2&#39;, &#39;3&#39;, &#39;A&#39;; &#39;4&#39;, &#39;5&#39;, &#39;6&#39;, &#39;B&#39;; &#39;7&#39;, &#39;8&#39;, &#39;9&#39;, &#39;C&#39;; &#39;*&#39;, &#39;0&#39;, &#39;#&#39;, &#39;D&#39; ]; % 读取或生成DTMF信号 [clean_signal, Fs] = generate_or_load_dtmf_signal(); % 使用您提供的函数添加不同信噪比的噪声 snr_levels = [ 0, -2, -5, -10, -20]; % 测试不同信噪比 results = cell(length(snr_levels), 2); for i = 1:length(snr_levels) fprintf(&#39;测试信噪比: %d dB\n&#39;, snr_levels(i)); % 添加噪声 noisy_signal = addDiffSnr4Student(clean_signal, snr_levels(i)); % 识别电话号码 phone_number = process_and_recognize(noisy_signal, Fs, tone_duration, pause_duration, ... low_freqs, high_freqs, dtmf_keys); results{i, 1} = snr_levels(i); results{i, 2} = phone_number; fprintf(&#39;识别结果: %s\n\n&#39;, phone_number); end % 显示最终结果 display_final_results(results, clean_signal); end function [signal, Fs] = generate_or_load_dtmf_signal() % 如果要从文件读取,取消下面注释并修改文件名 filename = ‘20231071364_实验二案例2_无噪DTMF.wav’; if exist(filename, ‘file’) [signal, Fs] = audioread(filename); if size(signal, 2) > 1 signal = mean(signal, 2); % 转为单声道 end end end function tone = generate_dtmf_tone(digit, duration, Fs) % DTMF频率映射 freq_map = containers.Map(); freq_map(1) = [697, 1209]; freq_map(‘2’) = [697, 1336]; freq_map(3) = [697, 1477]; freq_map(‘4’) = [770, 1209]; freq_map(‘5’) = [770, 1336]; freq_map(‘6’) = [770, 1477]; freq_map(7) = [852, 1209]; freq_map(‘8’) = [852, 1336]; freq_map(‘9’) = [852, 1477]; freq_map(‘0’) = [941, 1336]; freq_map(‘*’) = [941, 1209]; freq_map(‘#’) = [941, 1477]; freq_map(‘A’) = [697, 1633]; freq_map(‘B’) = [770, 1633]; freq_map(‘C’) = [852, 1633]; freq_map(‘D’) = [941, 1633]; if isKey(freq_map, digit) freqs = freq_map(digit); t = 0:1/Fs:duration-1/Fs; tone = 0.5 * sin(2*pi*freqs(1)*t) + 0.5 * sin(2*pi*freqs(2)*t); tone = tone(:); else tone = zeros(round(duration*Fs), 1); end end function DTMF = addDiffSnr4Student(dtmfData, snrDB) % 使用您提供的加噪函数 % 为 dtmfData 信号加上指定信噪比的高斯白噪声 DTMF = awgn(dtmfData, snrDB, ‘measured’); figure; plot(DTMF); hold on; plot(dtmfData, &#39;r&#39;); legend(&#39;加噪信号&#39;, &#39;原始信号&#39;); title([&#39;信噪比 = &#39;, num2str(snrDB), &#39; dB&#39;]); xlabel(&#39;采样点&#39;); ylabel(&#39;幅度&#39;); end function phone_number = process_and_recognize(signal, Fs, tone_duration, pause_duration, … low_freqs, high_freqs, dtmf_keys) % 完整的处理和识别流程 % 1. 预处理信号 processed_signal = advanced_preprocessing(signal, Fs); % 2. 检测和分割音调 tones = improved_tone_detection(processed_signal, Fs, tone_duration, pause_duration); % 3. 识别每个音调 phone_number = robust_frequency_recognition(tones, Fs, low_freqs, high_freqs, dtmf_keys); end function processed_signal = advanced_preprocessing(signal, Fs) % 改进的信号预处理 % 1. 带通滤波,保留DTMF频率范围 (600-1700 Hz) f_low = 600; f_high = 1700; % 使用切比雪夫滤波器,更好的阻带衰减 [b, a] = cheby2(6, 40, [f_low/(Fs/2), f_high/(Fs/2)], &#39;bandpass&#39;); filtered_signal = filter(b, a, signal); % 2. 使用中值滤波去除脉冲噪声 window_size = 5; if length(filtered_signal) > window_size filtered_signal = medfilt1(filtered_signal, window_size); end % 3. 能量归一化 processed_signal = filtered_signal / max(abs(filtered_signal)); end function tones = improved_tone_detection(signal, Fs, tone_duration, pause_duration) % 改进的音调检测算法 tone_length = round(tone_duration * Fs); pause_length = round(pause_duration * Fs); % 使用短时能量和谱熵进行端点检测 frame_size = 256; hop_size = 128; energy = []; spectral_entropy = []; for i = 1:hop_size:length(signal)-frame_size frame = signal(i:i+frame_size-1); % 计算帧能量 frame_energy = sum(frame.^2); energy = [energy; frame_energy]; % 计算谱熵 frame_fft = abs(fft(frame .* hamming(frame_size))); frame_fft = frame_fft(1:frame_size/2+1); frame_fft = frame_fft / sum(frame_fft); frame_fft(frame_fft == 0) = eps; % 避免log(0) entropy = -sum(frame_fft .* log(frame_fft)); spectral_entropy = [spectral_entropy; entropy]; end % 归一化能量和熵 energy_norm = energy / max(energy); entropy_norm = spectral_entropy / max(spectral_entropy); % 结合能量和熵的检测指标 detection_metric = energy_norm .* (1 - entropy_norm); % 自适应阈值 threshold = 0.1 * max(detection_metric) + 0.9 * mean(detection_metric); % 检测音调起始点 tone_starts = []; in_tone = false; min_tone_length = round(0.5 * tone_length / hop_size); for i = 1:length(detection_metric) if ~in_tone && detection_metric(i) > threshold tone_starts = [tone_starts; i]; in_tone = true; tone_counter = 1; elseif in_tone if detection_metric(i) <= threshold tone_counter = tone_counter + 1; if tone_counter > min_tone_length in_tone = false; end else tone_counter = 0; end end end % 提取音调片段 tones = {}; for i = 1:length(tone_starts) start_idx = (tone_starts(i) - 1) * hop_size + 1; end_idx = min(start_idx + tone_length - 1, length(signal)); if end_idx - start_idx + 1 >= 0.8 * tone_length tone_segment = signal(start_idx:end_idx); tones{end+1} = tone_segment; end end end function phone_number = robust_frequency_recognition(tones, Fs, low_freqs, high_freqs, dtmf_keys) % 改进的频率识别算法 phone_number = &#39;&#39;; freq_tolerance = 20; % 频率容差(Hz) for i = 1:length(tones) tone = tones{i}; % 使用改进的Goertzel算法 [detected_low, detected_high, confidence] = improved_goertzel_detection(... tone, Fs, low_freqs, high_freqs); % 基于置信度的决策 if confidence > 0.7 digit = map_frequencies_to_digit(detected_low, detected_high, ... low_freqs, high_freqs, dtmf_keys, freq_tolerance); phone_number = [phone_number, digit]; else phone_number = [phone_number, &#39;?&#39;]; % 无法识别的音调 end end end function [low_freq, high_freq, confidence] = improved_goertzel_detection(signal, Fs, low_freqs, high_freqs) % 改进的Goertzel频率检测 N = length(signal); % 检测低频组 low_results = zeros(length(low_freqs), 2); for i = 1:length(low_freqs) k = round(low_freqs(i) * N / Fs); magnitude = goertzel(signal, k); low_results(i, :) = [low_freqs(i), magnitude]; end % 检测高频组 high_results = zeros(length(high_freqs), 2); for i = 1:length(high_freqs) k = round(high_freqs(i) * N / Fs); magnitude = goertzel(signal, k); high_results(i, :) = [high_freqs(i), magnitude]; end % 寻找主要频率成分 [low_freq, low_conf] = find_dominant_frequency(low_results); [high_freq, high_conf] = find_dominant_frequency(high_results); % 综合置信度 confidence = (low_conf + high_conf) / 2; end function [dominant_freq, confidence] = find_dominant_frequency(freq_results) % 寻找主导频率并计算置信度 magnitudes = freq_results(:, 2); max_mag = max(magnitudes); mean_mag = mean(magnitudes); % 找到最大幅度对应的频率 [~, idx] = max(magnitudes); dominant_freq = freq_results(idx, 1); % 计算置信度:基于信噪比 if max_mag > 0 snr_ratio = (max_mag - mean_mag) / max_mag; confidence = max(0, min(1, snr_ratio * 2)); else confidence = 0; end end function magnitude = goertzel(signal, k) % Goertzel算法实现 N = length(signal); w = 2 * pi * k / N; cosine = cos(w); coeff = 2 * cosine; s_prev = 0; s_prev2 = 0; for i = 1:N s = signal(i) + coeff * s_prev - s_prev2; s_prev2 = s_prev; s_prev = s; end real_part = s_prev - s_prev2 * cosine; imag_part = s_prev2 * sin(w); magnitude = sqrt(real_part^2 + imag_part^2) / N; end function digit = map_frequencies_to_digit(low_freq, high_freq, low_freqs, high_freqs, dtmf_keys, tolerance) % 将频率映射到数字,考虑容差 % 找到最接近的低频 [~, low_idx] = min(abs(low_freqs - low_freq)); closest_low = low_freqs(low_idx); % 找到最接近的高频 [~, high_idx] = min(abs(high_freqs - high_freq)); closest_high = high_freqs(high_idx); % 检查频率是否在容差范围内 if abs(closest_low - low_freq) <= tolerance && abs(closest_high - high_freq) <= tolerance digit = dtmf_keys(low_idx, high_idx); else digit = &#39;?&#39;; end end function display_final_results(results, clean_signal) % 显示最终结果 figure(&#39;Position&#39;, [100, 100, 1000, 600]); % 显示原始信号 subplot(2,1,1); t = (0:length(clean_signal)-1) / 44100; plot(t, clean_signal); title(&#39;原始DTMF信号&#39;); xlabel(&#39;时间 (s)&#39;); ylabel(&#39;幅度&#39;); grid on; % 显示识别结果表格 subplot(2,1,2); axis off; % 创建结果表格 result_text = sprintf(&#39;=== DTMF电话号码识别结果 ===\n\n&#39;); result_text = [result_text, sprintf(&#39;%-8s %-15s\n&#39;, &#39;信噪比(dB)&#39;, &#39;识别结果&#39;)]; result_text = [result_text, sprintf(&#39;%-8s %-15s\n&#39;, &#39;---------&#39;, &#39;----------&#39;)]; for i = 1:size(results, 1) result_text = [result_text, sprintf(&#39;%-8d %-15s\n&#39;, results{i,1}, results{i,2})]; end text(0.1, 0.9, result_text, &#39;FontName&#39;, &#39;Courier New&#39;, &#39;FontSize&#39;, 12, ... &#39;VerticalAlignment&#39;, &#39;top&#39;); fprintf(&#39;\n%s&#39;, result_text); end % 运行改进的主函数 dtmf_phone_recognition_improved();在上面的代码的基础上提供抗信噪比,使在最小-30dB下,仍能提取出原号码13108363851
10-27
/*输入: 若干行,在每一行中给出整数N和A的值,(1<=N<=150,0<=A<=15) 对于20%的数据,有 1<=N<=12,0<=A<=5 对于40%的数据,有1<=N<=18,0<=A<=9 对于100%的数据,有1<=N<=150,0<=A<=15 从右上方下载p95.py并运行以生成随机测试数据 输出: 对于每一行,在一行中输出级数A+2A2+3A3+。。。+NAN =的整数值 样例输入 样例输出 3 3 102 4 4 1252 提示: 高精度*/ #include<iostream> using namespace std; struct ElemType { int digit; }; struct Bigint { ElemType* elem; int length = 0; int listsize = 0; }; void ADD(Bigint L1,Bigint L2,Bigint L3) { L1.listsize >= L2.listsize ? L3.listsize = (L1.listsize + 1) : L3.listsize = (L2.listsize + 1); L3.elem = new ElemType[L3.listsize]; int i = 0; for (; i < L1.length && i < L2.length; ++i) { if (i == 0) { L3.elem[i].digit = (L1.elem[i].digit + L2.elem[i].digit ) % 10; L3.length++; } else{ L3.elem[i].digit = (L1.elem[i].digit + L2.elem[i].digit + (L1.elem[i - 1].digit + L2.elem[i - 1].digit) / 10) % 10; L3.length++; } } for (; i < L1.length ; ++i) { if (i == L2.length) { L3.elem[i].digit = (L1.elem[i].digit + L2.elem[i].digit + (L1.elem[i - 1].digit + L2.elem[i - 1].digit) / 10) % 10; L3.length++; } else { L3.elem[i].digit = L1.elem[i].digit; L3.length++; } } for (; i < L2.length; ++i) { if (i == L1.length) { L3.elem[i].digit = (L1.elem[i].digit + L2.elem[i].digit + (L1.elem[i - 1].digit + L2.elem[i - 1].digit) / 10) % 10; L3.length++; } else { L3.elem[i].digit = L2.elem[i].digit; L3.length++; } } } int main() { int N, A; cin >> N >>A; Bigint L1,L2; int numer = A / 10 + 1; L1.length = numer; L1.listsize = numer; L1.elem = new ElemType[L1.listsize]; L1.elem[0].digit = A % 10; if (numer > 1) { L1.elem[1].digit = A / 10; } ADD(L1, L1, L2); for (int i = L2.length - 1; i >= 0; i--) { cout << L2.elem[i].digit; } }
10-07
```markdown ## 代码概述 该代码旨在计算级数 $ A + 2A^2 + 3A^3 + \cdots + N A^N $ 的值,使用**顺序表结构**模拟高精度整数运算。由于结果可能极大(如 $ N=150, A=15 $),需避免内置类型溢出。目要求不可使用 `vector`,故采用动态数组实现大数存储。 当前代码仅实现了部分功能:读取 $ N $ 和 $ A $,将 $ A $ 存入自定义大数结构,并尝试调用加法函数 `ADD` 计算 $ A + A $,但存在多处错误,未完成完整逻辑。 --- ## 代码解析 ### 1. 数据结构设计 ```cpp struct ElemType { int digit; // 每个节点存一位数字 }; struct Bigint { ElemType* elem; // 动态数组存储各位 int length = 0; // 当前位数 int listsize = 0; // 分配空间大小 }; ``` 意图是用链式顺序表存储大数的各位(逆序:个位在前),合理符合“不可用 vector”的限制。 --- ### 2. 加法函数 `ADD(Bigint L1, Bigint L2, Bigint L3)` #### 存在严重问- **参数传递方式错误**:`L3` 是按值传参,函数内修改不会反映到外部。 - **未初始化 `L3.elem` 内容就访问**:虽分配内存,但未清零或正确处理进位。 - **进位逻辑错误**: ```cpp L3.elem[i].digit = (L1.elem[i].digit + L2.elem[i].digit + (L1.elem[i - 1].digit + L2.elem[i - 1].digit) / 10) % 10; ``` 这里把前一位的和当作进位使用,完全错误。进位应来自上一位的加法结果,不能直接取原数之和除以10。 - **缺少最终进位处理**:例如 $9+9=18$ 应产生新一位 `1`,但代码未处理最高位进位。 - **分支冗余且错误**:三个循环中对 `i == L2.length` 等判断无意义,索引已越界。 --- ### 3. 主函数逻辑缺陷 ```cpp cin >> N >> A; ``` 只读取一组输入,未处理“若干行”输入(应为 `while(cin >> N >> A)`)。 接着试图将 $ A $ 转换为大数: ```cpp int numer = A / 10 + 1; L1.elem[0].digit = A % 10; if (numer > 1) { L1.elem[1].digit = A / 10; } ``` 此段用于将个位、十位拆开存储,基本正确(因 $ A \leq 15 $,最多两位)。但未设置 `length` 正确值(应设为 `numer`)。 最后调用 `ADD(L1, L1, L2);` 想计算 $ A + A $,但: - `L2` 未初始化,其 `elem` 为野指针; - `ADD` 函数无法返回结果(值传递,内部修改不生效); - 即使成功,也只是加了 $ A+A $,远未实现整个级数求和。 --- ### 4. 缺失的核心功能 - ❌ 幂运算 $ A^i $ - ❌ 系数乘法 $ i \times A^i $ - ❌ 高精度累加 - ❌ 完整的进位管理 - ❌ 多组输入循环 - ❌ 输出后释放内存(存在泄漏风险) --- ## 知识点 1. **高精度算术运算** 使用数组逐位存储大数,加法需逐位相加并正确处理进位。 2. **顺序表的应用** 手动管理动态数组模拟线性表,替代 vector 实现灵活存储。 3. **引用传递与函数接口设计** 函数需通过引用或指针修改结构体内容,否则形参修改无效。 ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值