Rust每日一练(Leetday0013) 解数独、外观数列、组合总和

news2024/11/24 3:01:11

目录

37. 解数独 Sudoku Solver  🌟🌟🌟

38. 外观数列 Count and Say  🌟🌟

39. 组合总和 Combination Sum  🌟🌟

🌟 每日一练刷题专栏 🌟

Rust每日一练 专栏

Golang每日一练 专栏

Python每日一练 专栏

C/C++每日一练 专栏

Java每日一练 专栏


37. 解数独 Sudoku Solver

编写一个程序,通过填充空格来解决数独问题。

数独的解法需 遵循如下规则

  1. 数字 1-9 在每一行只能出现一次。
  2. 数字 1-9 在每一列只能出现一次。
  3. 数字 1-9 在每一个以粗实线分隔的 3x3 宫内只能出现一次。(请参考示例图)

数独部分空格内已填入了数字,空白格用 '.' 表示。

示例 1:

输入:board = [
["5","3",".",".","7",".",".",".","."],
["6",".",".","1","9","5",".",".","."],
[".","9","8",".",".",".",".","6","."],
["8",".",".",".","6",".",".",".","3"],
["4",".",".","8",".","3",".",".","1"],
["7",".",".",".","2",".",".",".","6"],
[".","6",".",".",".",".","2","8","."],
[".",".",".","4","1","9",".",".","5"],
[".",".",".",".","8",".",".","7","9"]]

输出:
[["5","3","4","6","7","8","9","1","2"],
["6","7","2","1","9","5","3","4","8"],
["1","9","8","3","4","2","5","6","7"],
["8","5","9","7","6","1","4","2","3"],
["4","2","6","8","5","3","7","9","1"],
["7","1","3","9","2","4","8","5","6"],
["9","6","1","5","3","7","2","8","4"],
["2","8","7","4","1","9","6","3","5"],
["3","4","5","2","8","6","1","7","9"]]

解释:输入的数独如上图所示,唯一有效的解决方案如下所示:

提示:

  • board.length == 9
  • board[i].length == 9
  • board[i][j] 是一位数字或者 '.'
  • 题目数据 保证 输入数独仅有一个解

代码:

fn solve_sudoku(board: &mut Vec<Vec<char>>) {
    let mut pos: Vec<[usize; 2]> = Vec::new();
    let mut find = false;
    for i in 0..board.len() {
        for j in 0..board[0].len() {
            if board[i][j] == '.' {
                pos.push([i, j]);
            }
        }
    }
    put_sudoku(board, &pos, 0, &mut find);
}

fn put_sudoku(
    board: &mut Vec<Vec<char>>,
    pos: &Vec<[usize; 2]>,
    index: usize,
    succ: &mut bool,
) {
    if *succ {
        return;
    }
    if index == pos.len() {
        *succ = true;
        return;
    }
    for i in 1..=9 {
        if check_sudoku(board, pos[index], i) && !*succ {
            board[pos[index][0]][pos[index][1]] = (i as u8 + b'0') as char;
            put_sudoku(board, pos, index + 1, succ);
            if *succ {
                return;
            }
            board[pos[index][0]][pos[index][1]] = '.';
        }
    }
}

fn check_sudoku(board: &Vec<Vec<char>>, pos: [usize; 2], val: usize) -> bool {
    // 判断行是否有重复数字
    for i in 0..board[0].len() {
        if board[pos[0]][i] != '.' && (board[pos[0]][i] as u8 - b'0') as usize == val {
            return false;
        }
    }
    // 判断列是否有重复数字
    for i in 0..board.len() {
        if board[i][pos[1]] != '.' && (board[i][pos[1]] as u8 - b'0') as usize == val {
            return false;
        }
    }
    // 判断九宫格是否有重复数字
    let posx = pos[0] - pos[0] % 3;
    let posy = pos[1] - pos[1] % 3;
    for i in posx..posx + 3 {
        for j in posy..posy + 3 {
            if board[i][j] != '.' && (board[i][j] as u8 - b'0') as usize == val {
                return false;
            }
        }
    }
    true
}

fn main() {
    let mut board: Vec<Vec<char>> = vec![
        vec!['5', '3', '.', '.', '7', '.', '.', '.', '.'],
        vec!['6', '.', '.', '1', '9', '5', '.', '.', '.'],
        vec!['.', '9', '8', '.', '.', '.', '.', '6', '.'],
        vec!['8', '.', '.', '.', '6', '.', '.', '.', '3'],
        vec!['4', '.', '.', '8', '.', '3', '.', '.', '1'],
        vec!['7', '.', '.', '.', '2', '.', '.', '.', '6'],
        vec!['.', '6', '.', '.', '.', '.', '2', '8', '.'],
        vec!['.', '.', '.', '4', '1', '9', '.', '.', '5'],
        vec!['.', '.', '.', '.', '8', '.', '.', '7', '9'],
    ];

    solve_sudoku(&mut board);

    for row in &board {
        for col in row {
            print!("{} ", (*col as u8 - b'0') as usize);
        }
        println!();
    }

    let answer: Vec<Vec<char>> = vec![
        vec!['5', '3', '4', '6', '7', '8', '9', '1', '2'],
        vec!['6', '7', '2', '1', '9', '5', '3', '4', '8'],
        vec!['1', '9', '8', '3', '4', '2', '5', '6', '7'],
        vec!['8', '5', '9', '7', '6', '1', '4', '2', '3'],
        vec!['4', '2', '6', '8', '5', '3', '7', '9', '1'],
        vec!['7', '1', '3', '9', '2', '4', '8', '5', '6'],
        vec!['9', '6', '1', '5', '3', '7', '2', '8', '4'],
        vec!['2', '8', '7', '4', '1', '9', '6', '3', '5'],
        vec!['3', '4', '5', '2', '8', '6', '1', '7', '9'],
    ];
    // 判断与答案是否一致
    let mut equal = true;
    for i in 0..board.len() {
        for j in 0..board[0].len() {
            if board[i][j] != answer[i][j] {
                equal = false;
                break;
            }
        }
        if !equal {
            break;
        }
    }
    println!("{}", equal);
}

输出:

5 3 4 6 7 8 9 1 2
6 7 2 1 9 5 3 4 8
1 9 8 3 4 2 5 6 7
8 5 9 7 6 1 4 2 3
4 2 6 8 5 3 7 9 1
7 1 3 9 2 4 8 5 6
9 6 1 5 3 7 2 8 4
2 8 7 4 1 9 6 3 5
3 4 5 2 8 6 1 7 9
true


38. 外观数列 Count and Say

给定一个正整数 n ,输出外观数列的第 n 项。

「外观数列」是一个整数序列,从数字 1 开始,序列中的每一项都是对前一项的描述。

你可以将其视作是由递归公式定义的数字字符串序列:

  • countAndSay(1) = "1"
  • countAndSay(n) 是对 countAndSay(n-1) 的描述,然后转换成另一个数字字符串。

前五项如下:

1.     1
2.     11
3.     21
4.     1211
5.     111221
第一项是数字 1 描述前一项,这个数是 1 即 “ 一 个 1 ”,记作 "11"
描述前一项,这个数是 11 即 “ 二 个 1 ” ,记作 "21"
描述前一项,这个数是 21 即 “ 一 个 2 + 一 个 1 ” ,记作 "1211"
描述前一项,这个数是 1211 即 “ 一 个 1 + 一 个 2 + 二 个 1 ” ,记作 "111221"

要 描述 一个数字字符串,首先要将字符串分割为 最小 数量的组,每个组都由连续的最多 相同字符 组成。然后对于每个组,先描述字符的数量,然后描述字符,形成一个描述组。要将描述转换为数字字符串,先将每组中的字符数量用数字替换,再将所有描述组连接起来。

例如,数字字符串 "3322251" 的描述如下图:

示例 1:

输入:n = 1
输出:"1"
解释:这是一个基本样例。

示例 2:

输入:n = 4
输出:"1211"
解释:
countAndSay(1) = "1"
countAndSay(2) = 读 "1" = 一 个 1 = "11"
countAndSay(3) = 读 "11" = 二 个 1 = "21"
countAndSay(4) = 读 "21" = 一 个 2 + 一 个 1 = "12" + "11" = "1211"

提示:

  • 1 <= n <= 30

代码:

fn count_and_say(n: i32) -> String {
    if n == 1 {
        return String::from("1");
    }
    let prev = count_and_say(n - 1);
    let mut res = String::new();
    let mut i = 0;
    let mut j = 0;
    while j <= prev.len() {
        if j == prev.len() || prev.chars().nth(j) != prev.chars().nth(i) {
            res += &(j - i).to_string();
            res += &prev.chars().nth(i).unwrap().to_string();
            i = j;
        }
        j += 1;
    }
    res
}

fn main() {
    for i in 1..=5 {
        println!("{}", count_and_say(i));
    }
}

输出:

1
11
21
1211
111221


39. 组合总和 Combination Sum

给你一个 无重复元素 的整数数组 candidates 和一个目标整数 target ,找出 candidates 中可以使数字和为目标数 target 的 所有 不同组合 ,并以列表形式返回。你可以按 任意顺序 返回这些组合。

candidates 中的 同一个 数字可以 无限制重复被选取 。如果至少一个数字的被选数量不同,则两种组合是不同的。 

对于给定的输入,保证和为 target 的不同组合数少于 150 个。

示例 1:

输入:candidates = [2,3,6,7], target = 7
输出:[[2,2,3],[7]]
解释:
2 和 3 可以形成一组候选,2 + 2 + 3 = 7 。注意 2 可以使用多次。
7 也是一个候选, 7 = 7 。仅有这两种组合。

示例 2:

输入: candidates = [2,3,5], target = 8
输出: [[2,2,2,2],[2,3,3],[3,5]]

示例 3:

输入: candidates = [2], target = 1
输出: []

提示:

  • 1 <= candidates.length <= 30
  • 1 <= candidates[i] <= 200
  • candidate 中的每个元素都 互不相同
  • 1 <= target <= 500

代码1: 回溯法

package main

import "fmt"

func combinationSum(candidates []int, target int) [][]int {
	var res [][]int
	var backtrack func([]int, int, int)
	backtrack = func(path []int, sum int, start int) {
		if sum >= target {
			if sum == target {
				res = append(res, append([]int{}, path...))
				return
			}
			return
		}
		for i := start; i < len(candidates); i++ {
			path = append(path, candidates[i])
			backtrack(path, sum+candidates[i], i)
			path = path[:len(path)-1]
		}
	}
	backtrack([]int{}, 0, 0)
	return res
}

func main() {

	candidates := []int{2, 3, 6, 7}
	fmt.Println(combinationSum(candidates, 7))

	candidates = []int{2, 3, 5}
	fmt.Println(combinationSum(candidates, 8))

	candidates = []int{2}
	fmt.Println(combinationSum(candidates, 1))

}

输出:

[[2, 2, 3], [7]]
[[2, 2, 2, 2], [2, 3, 3], [3, 5]]
[]

代码2: 回溯法

fn combination_sum(candidates: Vec<i32>, target: i32) -> Vec<Vec<i32>> {
    if candidates.is_empty() {
        return Vec::new();
    }
    let mut res = Vec::new();
    let mut c = Vec::new();
    let mut nums = candidates.clone();
    nums.sort();
    backtrack(&nums, target, 0, &mut c, &mut res);
    res
}

fn backtrack(nums: &Vec<i32>, target: i32, index: usize, c: &mut Vec<i32>, res: &mut Vec<Vec<i32>>) {
    if target <= 0 {
        if target == 0 {
            res.push(c.clone());
        }
        return;
    }
    for i in index..nums.len() {
        if nums[i] > target {
            break;
        }
        c.push(nums[i]);
        backtrack(nums, target - nums[i], i, c, res);
        c.pop();
    }
}

fn main() {
    let candidates = vec![2, 3, 6, 7];
    println!("{:?}", combination_sum(candidates, 7));
    
    let candidates = vec![2, 3, 5];
    println!("{:?}", combination_sum(candidates, 8));
    
    let candidates = vec![2];
    println!("{:?}", combination_sum(candidates, 1));
}

🌟 每日一练刷题专栏 🌟

持续,努力奋斗做强刷题搬运工!

👍 点赞,你的认可是我坚持的动力! 

🌟 收藏,你的青睐是我努力的方向! 

评论,你的意见是我进步的财富!  

 主页:https://hannyang.blog.csdn.net/

Rust每日一练 专栏

(2023.5.16~)更新中...

Golang每日一练 专栏

(2023.3.11~)更新中...

Python每日一练 专栏

(2023.2.18~2023.5.18)暂停更

C/C++每日一练 专栏

(2023.2.18~2023.5.18)暂停更

Java每日一练 专栏

(2023.3.11~2023.5.18)暂停更

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/606077.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

常微分方程(ODE)求解方法总结

常微分&#xff08;ODE&#xff09;方程求解方法总结 1 常微分方程&#xff08;ODE&#xff09;介绍1.1 微分方程介绍和分类1.2 常微分方程得计算方法1.3 线性微分方程求解的推导过程 2 一阶常微分方程&#xff08;ODE&#xff09;求解方法2.1 欧拉方法2.1.1 欧拉方法的改进思路…

逻辑推理——弟弟的编程课

前言 这篇文章不写代码&#xff0c;不科普知识。而是推理&#xff01; 这是我弟弟编程课上的一个同学&#xff1b;不是我的同学&#xff0c;我都成年了&#xff0c;这还是个小毛孩&#xff01; 这是他们学的&#xff1a; 乍一看这没任何问题&#xff0c;还有人会说&#xff…

谷歌地图模型自动下载

本工具是收费软件&#xff0c;学生党勿扰&#xff0c;闹眼子党勿扰 本工具收费1000元 视频教程 1 概述 记得去年写过一篇关于谷歌地图模型提取的博客&#xff0c;得到了广泛好评。有很多同学提出&#xff0c;能不能自动下载谷歌地图模型&#xff0c;由于提出此需求的人太多了…

【起点到终点 走哪条路径使得(路径长度排序从大到小后) 第k+1条边最小】通信线路

专注 效率 记忆 预习 笔记 复习 做题 欢迎观看我的博客&#xff0c;如有问题交流&#xff0c;欢迎评论区留言&#xff0c;一定尽快回复&#xff01;&#xff08;大家可以去看我的专栏&#xff0c;是所有文章的目录&#xff09;   文章字体风格&#xff1a; 红色文字表示&#…

单片机GD32F303RCT6 (Macos环境)开发 (三十四)—— 数字加速度计 (ADXL345)

数字加速度计 &#xff08;ADXL345&#xff09;- 计算xyz轴重力值 1、i2c总线读取 1、接线 上一节的软件模式i2c的方式&#xff0c;选择PB10(SCL) PB11(SDA)。 GD32 ADXL345PB10 --------------- SCLPB11 --------------- SDA3.3 --…

Eclipse 教程 完结

Eclipse 快捷键 关于快捷键 Eclipse 的很多操作都提供了快捷键功能&#xff0c;我们可以通过键盘就能很好的控制 Eclipse 各个功能&#xff1a; 使用快捷键关联菜单或菜单项使用快捷键关联对话窗口或视图或编辑器使用快捷键关联工具条上的功能按钮 Eclipse 快捷键列表可通过…

《crossfire》游戏分析

文章目录 一、 穿越火线简介和定位二、 游戏发行三、 用户基础四、 游戏玩法枪王排位团队竞技爆破模式歼灭模式突围模式幽灵模式生化模式个人竞技挑战模式跳跳乐地图工坊 五、 游戏竞技公平性cf竞技公平性 六、CF火热到现在的原因分析1.时代、空间背景2.用户基础3.丰富的游戏模…

【iOS】—— nil、Nil、NULL和NSNull学习

nil、Nil、NULL和NSNull 文章目录 nil、Nil、NULL和NSNullnilNSNullNilNULL总结&#xff1a; 我们先来看看这几个苹果官方文档的解释&#xff1a; nil&#xff1a;Defines the id of a null instance.&#xff08;定义空实例的id&#xff09;Nil&#xff1a;Defines the id of…

给编程初学者的一封信

提醒&#xff1a;以下内容仅做参考&#xff0c;具体请自行设计。 随着信息技术的快速发展&#xff0c;编程已经成为一个越来越重要的技能。那么&#xff0c;我们该如何入门编程呢&#xff1f;欢迎大家积极讨论 一、自学编程需要注意什么&#xff1f; 要有足够的时间、精力等…

大数据治理入门系列:数据目录

在元数据管理一文中&#xff0c;我们曾将数据比喻为一本本的书&#xff0c;将书的作者、出版时间等信息比喻为元数据。试想一下&#xff0c;假如你是一名新任的图书管理员&#xff0c;如何快速掌握图书馆的馆藏情况呢&#xff1f;假如你是一名读者&#xff0c;如何快速找到你需…

Redis GEO功能详细介绍与实战

一、概述 Redis的Geo功能主要用于存储地理位置信息&#xff0c;并对其进行操作。该功能在Redis 3.2版本新增。Redis Geo操作方法包括&#xff1a; geoadd&#xff1a;添加地理位置的坐标&#xff1b;geopos&#xff1a;获取地理位置的坐标&#xff1b;geodist&#xff1a;计算…

第五届湖北省大学生程序设计竞赛(HBCPC 2023)vp赛后补题

Problem - B - Codeforces 思路&#xff1a; 数位dp&#xff0c;如果我们暴力的计算的状态的话&#xff0c;显然就是记录每个数字出现几次。但是显然这样难以发挥数位dp的记忆化功效&#xff0c;因为只有出现次数相同&#xff0c;你是什么数字&#xff0c;实际是无所谓的。所…

I2C学习笔记——I2C协议学习

1、I2C简介&#xff1a;一种简单、双线双向的同步串行总线&#xff0c;利用串行时钟线(SCL)和串行数据线(SDA)在连接总线的两个器件之间进行信息传递&#xff1b; 数据传输是通过对SCL和SDA线高低电平时序的控制&#xff0c;来产生I2C总线协议所需要的信号。在总线空闲状态时&a…

【Linux C】基于树莓派/香橙派的蓝牙服务端——支持多蓝牙设备接入

一、需求 在树莓派/香橙派上利用开发板自带的蓝牙作为一个蓝牙服务端&#xff08;主机&#xff09;&#xff0c;允许外来设备&#xff08;从机&#xff09;通过蓝牙接入进行通信&#xff0c;通信格式为透传方式&#xff1b;采用的编程语言为Linux C 二、环境准备 bluez安装 …

三波混频下的相位失配原理

原理推导 在四波混频情况下&#xff0c;实现零相位失配是一件很困难的事情。因为在四波混频中&#xff0c;相位调制和增益都依赖于相同的参数&#xff0c;即克尔非线性 γ \gamma γ。这个问题可以用嵌入在传输线上的辅助共振元件的复杂色散工程来部分解决。 但是在三波混频中…

ceph集群监控

文章目录 Ceph Dashboard启用dashboard插件dashboard启用ssl Promethues监控ceph启用prometheus模块配置prometheus采集数据grafana数据展示 Ceph Dashboard ceph-dashboard官方介绍&#xff1a;https://docs.ceph.com/en/latest/mgr/dashboard/ Ceph Dashboard是一个内置的c…

数据库系统概论---选择题刷题实训

&#xff08;一&#xff09;选择题 1.下列选项中&#xff0c;不属于关系模型三要素的是&#xff08; C &#xff09; A&#xff0e;数据结构 B&#xff0e;数据操纵 C&#xff0e;数据安全 D&#xff0e;数据完整性规则 2.保证数据库…

【Spring】透过Spring源码查看Bean的命名转换规则

近期在写Spring项目的时候&#xff0c;需要通过注解的形式去替代之前直接将Bean存放在Spring容器这种方式&#xff0c;以此来简化对于Bean对象的操作&#xff0c;但是这样无法通过准确的Id去获取到相应的Bean对象了 测试观察 首先&#xff0c;如果要将指定的对象存放到Spring中…

SQL注入基础知识

文章目录 一、注入的分类1.基于服务器收到的响应2.基于处理输入的SQL查询&#xff08;数据类型&#xff09;3.基于程度和顺序的注入&#xff08;哪里受了影响&#xff09;4、基于注入点位置 二、系统函数1.字符串连接函数2.一般用于尝试的语句3.union操作符的介绍 总结 一、注入…

caught (in promise) RangeError: Maximum call stack size exceeded-vue前置导航守卫死循环

报错图 产生场景 1.近期在搭建移动端的架子时&#xff0c;在写路由守卫时&#xff0c;发现陷入死循环&#xff0c;报错意思是循环超出栈。。 2.后面排查了一圈问题之后&#xff0c;发现这个问题很小&#xff0c;但很难发现&#xff0c;在此记录。 3.vue 路由的导航守卫并不是…