LeetCode每日一题(233. Number of Digit One)

该博客介绍了LeetCode第233题的解决方案,重点是计算在所有非负整数中数字1出现的总次数。作者使用动态规划的方法,通过dp数组来跟踪不同位置上数字1的数量,考虑了前一位是否达到最大值的情况。代码虽然起初遇到理解问题,但最终成功实现并得到正确结果。

Given an integer n, count the total number of digit 1 appearing in all non-negative integers less than or equal to n.


做了半天才发现人家要的是 1 这个 digit 的数量,不是 number 的数量, 又改了改,好歹是通过了, 但是代码确实丑。凑活看吧。

本来开始想用反向思维来解, 就是总数-所有不包含 1 的数字数量, 但是好像不太灵, 后来又发现是要 digit 的数量, 所以就彻底放弃直接用 dp 的方法来解 dp(i, reach_top, ones), i 代表第 i 位数字(从 0 开始), reach_top 代表前一位数字是不是已经达到最大值, ones 代表当前的 1 的数量。如果 reach_top = true, 那我们就只能从 0…=digits[i]中来挑选当前位的数字, 否则, 我们就可以从 0…=9 中选择。对于最后一位的处理同样要考虑 reach_top 和 ones, 具体的看代码吧



use std::collections::HashMap;

impl Solution {
    fn rc(digits: &Vec<i32>, i: usize, reach_top: bool, ones: i32, cache: &mut HashMap<(usize, bool, i32), i32>) -> i32 {
        let mut ans = 0;
        // 如果是最后一位
        if i == digits.len() - 1 {
            // 如果上一位已经是最大
            if reach_top {
                // 如果前面的几位中已经包含1
                if ones > 0 {
                    // 如果当前位为0, 将前面几位的1计入答案
                    if digits[i] == 0 {
                        ans += ones;
                        return ans;
                    }
                    // 如果当前位大于0, 当当前位不为1的时候每个数字都对答案贡献ones, 当当前位位1时, 该数字对答案贡献ones + 1
                    ans += digits[i] * ones;
                    ans += ones + 1;
                    return ans;
                }
                // 如果前面几位不包含1且当前为大于0, 只有当前位为1的时候,向答案贡献1
                if digits[i] > 0 {
                    ans += 1;
                    return ans;
                }
                // 如果前几位不包含1且当前位为0, 没有任何包含1的数字可用
                return 0;
            }
            // 如果上一位不是最大, 且前几位包含1, 当当前位不为1时, 每个数字向答案贡献ones, 当当前位为1时, 每个数字向答案贡献ones+1
            if ones > 0 {
                ans += 9 * ones;
                ans += ones + 1;
                return ans;
            }
            // 如果上一位不是最大, 且前几位不包含1, 只有当前位为1时向答案贡献1
            ans += 1;
            return ans;
        }
        if reach_top {
            for j in 0..=digits[i] {
                let next = if let Some(c) = cache.get(&(i + 1, j == digits[i], ones + if j == 1 { 1 } else { 0 })) {
                    *c
                } else {
                    Solution::rc(digits, i + 1, j == digits[i], ones + if j == 1 { 1 } else { 0 }, cache)
                };
                ans += next;
            }
        } else {
            for j in 0..10 {
                let next = if let Some(c) = cache.get(&(i + 1, false, ones + if j == 1 { 1 } else { 0 })) {
                    *c
                } else {
                    Solution::rc(digits, i + 1, false, ones + if j == 1 { 1 } else { 0 }, cache)
                };
                ans += next;
            }
        }
        cache.insert((i, reach_top, ones), ans);
        ans
    }
    pub fn count_digit_one(n: i32) -> i32 {
        let digits: Vec<i32> = n.to_string().chars().map(|c| c.to_string().parse::<i32>().unwrap()).collect();
        if digits.len() == 1 {
            if digits[0] == 0 {
                return 0;
            }
            return 1;
        }
        let mut ans = 0;
        let mut cache = HashMap::new();
        for d in 0..=digits[0] {
            ans += Solution::rc(&digits, 1, d == digits[0], if d == 1 { 1 } else { 0 }, &mut cache);
        }
        ans as i32
    }
}
### LeetCode Problem 37: Sudoku Solver #### Problem Description The task involves solving a partially filled Sudoku puzzle. The input is represented as a two-dimensional integer array `board` where each element can be either a digit from '1' to '9' or '.' indicating empty cells. #### Solution Approach To solve this problem, one approach uses backtracking combined with depth-first search (DFS). This method tries placing numbers between 1 and 9 into every cell that contains '.', checking whether it leads to a valid solution by ensuring no conflicts arise within rows, columns, and subgrids[^6]. ```cpp void solveSudoku(vector<vector<char>>& board) { backtrack(board); } bool backtrack(vector<vector<char>> &board){ for(int row = 0; row < 9; ++row){ for(int col = 0; col < 9; ++col){ if(board[row][col] != '.') continue; for(char num='1';num<='9';++num){ if(isValidPlacement(board,row,col,num)){ placeNumber(num,board,row,col); if(backtrack(board)) return true; removeNumber(num,board,row,col); } } return false; } } return true; } ``` In the provided code snippet: - A function named `solveSudoku()` initiates the process. - Within `backtrack()`, nested loops iterate over all positions in the grid looking for unassigned spots denoted by '.' - For any such spot found, attempts are made to insert digits ranging from '1' through '9'. - Before insertion, validation checks (`isValidPlacement`) ensure compliance with Sudoku rules regarding uniqueness per row/column/subgrid constraints. - If inserting a number results in reaching a dead end without finding a complete solution, removal occurs before trying another possibility. This algorithm continues until filling out the entire board correctly or exhausting possibilities when returning failure status upward along recursive calls stack frames. --related questions-- 1. How does constraint propagation improve efficiency while solving puzzles like Sudoku? 2. Can genetic algorithms provide alternative methods for tackling similar combinatorial problems effectively? 3. What optimizations could enhance performance further beyond basic DFS/backtracking techniques used here?
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值