【华为OD机试真题】【2024年E卷】字符串拼接-DFS回溯全排列剪枝去重(C++/Java/Python)

文章目录

      • 分值:200
      • 题目描述
      • 思路
      • 复杂度分析
      • AC 代码

分值:200

题目描述

给定 M 个字符(a-z),从中取出任意字符(每个字符只能用一次)拼接成长度为 N 的字符串,要求相同的字符不能相邻。
计算出给定的字符列表能拼接出多少种满足条件的字符串,无法拼接出满足条件的字符串则返回 0。
输入描述:
给定长度为 M 的字符列表和结果字符串的长度 N ,中间使用空格 拼接。
输出描述:
输出满足条件的字符串个数。

示例1
输入:
abc 1
输出:
3
解释:
给定的字符为 abc ,结果字符申长度为 1 ,可以拼接成 a、b、c ,共 3 种。

示例1
输入:
qwertyuiopasdfghjklzxcvbnm 5
输出:
7893600
解释:
此用例为比较极限的用例,写完代码后跑一下这个用例看一下大概用时多少,确保在 1s 内跑完。

Tips:

  • 0 < M < 30
  • 0 < N ≤ 5

思路

  • 本题考查的是DFS回溯去重。
  • 思考1:如果输入的字符串不包含重复字符,该怎么做?全排列
  • 思考2:如果输入的字符串包含重复字符,该怎么做?全排列+去重
  • 思考3:如何优雅地去重?

    首先将字符串 s 转成字符数组 arr,对字符数组排序,排序之后,相同字符位于字符数组中的相邻位置,可以利用这一特点去重。
    对于去重操作,需要考虑产生重复排列的原因。如果一个字符在字符数组中出现 k 次,则对于任意一个排列,将这 k 个字符的相对顺序交换之后会得到与原排列重复的排列,因此,为了避免重复排列,需要确保这 k 个字符加入排列的顺序是固定的。具体而言,当 i > 0 时,如果 arr[i] = arr[i − 1](此时字符数组 arr 已排序),则需要确保 arr[i − 1]arr[i] 之前加入排列。
    根据上述分析,在排序后的字符数组 arr 中遍历到下标 i 时,以下两种情况不应将 arr[i] 加入当前排列。
    1.如果 arr[i] 已经加入当前排列,则不能多次加入当前排列。
    2.如果当 i > 0 时,arr[i] = arr[i − 1]arr[i − 1] 未加入当前排列,则不能将 arr[i] 加入当前排列,否则 arr[i − 1] 将在 arr[i] 之后加入当前排列,导致出现重复排列。

复杂度分析

  • 时间复杂度: O ( N M ) O(N^M) O(NM),其中N为输入的字符串的长度,M为目标字符串的长度。
  • 空间复杂度: O ( N ) O(N) O(N),其中N为输入的字符串的长度。

AC 代码

C++ 版

#include <bits/stdc++.h>
using namespace std;
int ans = 0, n, vis[31];
void dfs(string &cur, string &s)
{
    // 递归边界
    if (cur.size() == n)
    {
        ans++;
        return;
    }
    for (int i = 0; i < s.size(); i++)
    {
        // 防止生成重复字符串
        if (vis[i] || (i > 0 && s[i] == s[i - 1] && !vis[i - 1]) || (cur.size() > 0 && cur.back() == s[i]))
        {
            continue;
        }
        vis[i] = true;
        cur += s[i];
        dfs(cur, s);
        cur.pop_back();
        vis[i] = false;
    }
}
int main()
{
    string str, cur = "";
    memset(vis, 0, sizeof(vis));
    cin >> str >> n;
    sort(str.begin(), str.end());
    dfs(cur, str);
    cout << ans << endl;
    return 0;
}

JAVA 版

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Scanner;

public class Main {
    static int ans = 0;
    static int n;
    static int[] vis;

    public static void dfs(List<Character> cur, String s) {
        if (cur.size() == n) {
            ans++;
            return;
        }
        for (int i = 0; i < s.length(); i++) {
            if (vis[i] == 1 || (i > 0 && s.charAt(i) == s.charAt(i - 1) && vis[i - 1] == 0) || (cur.size() > 0 && cur.get(cur.size() - 1) == s.charAt(i))) {
                continue;
            }
            vis[i] = 1;
            cur.add(s.charAt(i));
            dfs(cur, s);
            cur.remove(cur.size() - 1);
            vis[i] = 0;
        }
    }

    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        String str = scanner.next();
        n = scanner.nextInt();
        vis = new int[31];
        Arrays.fill(vis, 0);
        char[] charArray = str.toCharArray();
        Arrays.sort(charArray);
        str = new String(charArray);
        List<Character> cur = new ArrayList<>();
        dfs(cur, str);
        System.out.println(ans);
    }
}

Python 版

ans = 0
n = 0
vis = [0] * 31
cur = []
s = ''

def dfs():
    global ans
    if len(cur) == n:
        ans += 1
        return
    for i in range(len(s)):
        if vis[i] or (i > 0 and s[i] == s[i - 1] and not vis[i - 1]) or (len(cur) > 0 and cur[-1] == s[i]):
            continue
        vis[i] = 1
        cur.append(s[i])
        dfs()
        cur.pop()
        vis[i] = 0

if __name__ == "__main__":
    str_input = input().split()
    str = str_input[0]
    n = int(str_input[1])
    vis = [0] * 31
    s = s.join(sorted(str))
    dfs()
    print(ans)

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

探索 Seaborn Palette 的奥秘:为数据可视化增色添彩

一、引言 在数据科学的世界里&#xff0c;视觉传达是不可或缺的一环。一个好的数据可视化不仅能传递信息&#xff0c;还能引发共鸣。Seaborn 是 Python 中一款广受欢迎的可视化库&#xff0c;而它的调色板&#xff08;palette&#xff09;功能&#xff0c;则为我们提供了调配绚…

Sigrity System Explorer Snip Via Pattern From Layout模式从其它设计中截取过孔模型和仿真分析操作指导

Sigrity System Explorer Snip Via Pattern From Layout模式从其它设计中截取过孔模型和仿真分析操作指导 Sigrity System Explorer Snip Via Pattern From Layout模式支持从其它设计中截取过孔模型用于仿真分析,同样以差分模板为例 具体操作如下 双击打开System Explorer软件…

数据分析实战—玻璃类别分类

1.实战内容 (1) 加载玻璃类别数据集&#xff0c;划分训练集、测试集 import pandas as pd import numpy as np pd.set_option(display.max_columns, None) pd.set_option(display.max_rows, None) # 读取数据集 glass pd.read_csv(glass.csv, encodinggbk, headerNone) glas…

Hive是什么,Hive介绍

官方网站&#xff1a;Apache Hive Hive是一个基于Hadoop的数据仓库工具&#xff0c;主要用于处理和查询存储在HDSF上的大规模数据‌。Hive通过将结构化的数据文件映射为数据库表&#xff0c;并提供类SQL的查询功能&#xff0c;使得用户可以使用SQL语句来执行复杂的​MapReduce任…

GIN

gin是什么 Gin 是一个用 Go (Golang) 编写的 HTTP Web 框架。 它具有类似 Martini 的 API&#xff0c;但性能比 Martini 快 40 倍。如果你需要极好的性能&#xff0c;使用 Gin 吧。 特点&#xff1a;gin是golang的net/http库封装的web框架&#xff0c;api友好&#xff0c;注…

初始Python篇(13)—— 模块以及Python中常用的内置模块

找往期文章包括但不限于本期文章中不懂的知识点&#xff1a; 个人主页&#xff1a;我要学编程(ಥ_ಥ)-CSDN博客 所属专栏&#xff1a; Python 目录 模块的概念 模块的导入 包的概念以及使用 主程序运行 Python中常用的内置模块 random模块 time模块 datetime模块 …

时间序列异常值检测方法

文章目录 一、基于统计的方法1.1、标准差1.2、箱线图1.3、Z-Score法 二、基于机器学习算法的方法2.1、K-NN2.2、孤立森林 三、基于密度的方法3.1、LOF3.2、DBSCAN密度聚类 时间序列相关参考文章&#xff1a; 时间序列预测算法—ARIMA 时间序列预测算法—Prophet 时间序列分类任…

8K+Red+Raw+ProRes422分享5个影视级视频素材网站

Hello&#xff0c;大家好&#xff0c;我是后期圈&#xff01; 在视频创作中&#xff0c;电影级的视频素材能够为作品增添专业质感&#xff0c;让画面更具冲击力。无论是广告、电影短片&#xff0c;还是品牌宣传&#xff0c;高质量的视频素材都是不可或缺的资源。然而&#xff…

顺序表的操作

注意位序和数组下标的关系 插入&#xff1a; 插入的时间复杂度&#xff1a; 最深层语句&#xff1a; 最好情况 最坏情况 平均情况 删除&#xff1a; 查找&#xff1a;

五、windows上vscode构建c/c++环境

1、安装vscode 官网下载界面&#xff1a;https://code.visualstudio.com/Download 请根据电脑系统安装所需版本点击下载链接&#xff08;一般情况下点击windows按钮即可&#xff09;鼠标左键双击&#xff0c;即可运行安装程序&#xff0c;点击【确认】&#xff1b;选择安装路径…

Spring实例化的基本流程和Bean处理器

目录 Spring实例化的基本流程 Bean的处理器 Bean工厂后处理器&#xff08;BeanFactoryPostProcessor&#xff09; 动态注册beanDefinition Bean后处理器&#xff08;BeanPostProcessor&#xff09; Spring实例化的基本流程 在了解处理器之前&#xff0c;要清除spring实例化…

【SH】Ubuntu Server 24搭建Web服务器访问Python程序研发笔记

文章目录 说个问题写个方案一、安装Ubuntu Server二、安装Web服务器采用Nginx服务器 三、安装Python及依赖创建项目虚拟环境 四、安装Python Web框架采用Flask框架创建和运行Flask应用&#xff08;以后的重点&#xff09; 五、安装WSGI服务器采用Gunicorn 六、配置Nginx七、验证…

109.【C语言】数据结构之求二叉树的高度

目录 1.知识回顾&#xff1a;高度&#xff08;也称深度&#xff09; 2.分析 设计代码框架 返回左右子树高度较大的那个的写法一:if语句 返回左右子树高度较大的那个的写法二:三目操作符 3.代码 4.反思 问题 出问题的代码 改进后的代码 执行结果 1.知识回顾&#xf…

瑞吉外卖项目学习笔记(二)Swagger、logback、表单校验和参数打印功能的实现

瑞吉外卖项目学习笔记(一)准备工作、员工登录功能实现 文章目录 3 项目组件优化3.1 实现Swagger文档输出3.2 实现logback日志打印3.3 实现表单校验功能3.4 实现请求参数和响应参数的打印 3 项目组件优化 3.1 实现Swagger文档输出 1&#xff09;在application.yml中增加knife4…

OpenEuler 22.03 安装 flink-1.17.2 集群

零&#xff1a;规划 本次计划安装三台OpenEuler 22.03 版本操作系统的服务器&#xff0c;用于搭建 flink 集群。这里使用flink1.17.2 的原因&#xff0c;是便于后续与springboot的整合 服务器名IP地址作用其他应用flink01192.168.159.133主jdk11、flink-1.17.2flink02192.168.…

[数据结构] 链表

目录 1.链表的基本概念 2.链表的实现 -- 节点的构造和链接 节点如何构造? 如何将链表关联起来? 3.链表的方法(功能) 1).display() -- 链表的遍历 2).size() -- 求链表的长度 3).addFirst(int val) -- 头插法 4).addLast(int val) -- 尾插法 5).addIndex -- 在任意位置…

20241220在荣品开发板PRO-RK3566的buildroot下适配gc2093

20241220在荣品开发板PRO-RK3566的buildroot下适配gc2093 2024/12/20 16:00 余顺?PRO-RK3566开发板 挂 gc2093模块。刷 buildroot的预编译固件。 update-pro-rk3566-buildroot-hdmi-20231130-034633.img 1、现在发现 qcamera的 拍照Capture、Record录像模式都是640x480分辨率…

实习冲刺数据库练习-01 基础查询

原题链接&#xff1a;牛客网在线编程_SQL篇_非技术快速入门 数据表示例&#xff1a; 根据数据表示例要求我们完成以下查询&#xff1a; &#xff08;1&#xff09;获取用户信息表中所有的数据&#xff0c;请你取出相应结果 &#xff08;2&#xff09;获取用户的设备id对应的…

【Mars3d】设置backgroundImage、map.scene.skyBox、backgroundImage来回切换

相关链接&#xff1a; http://mars3d.cn/editor-vue.html?keyex_1_2_1&idmap/other/backgroundImg 实现代码&#xff1a; export function show1() {map.setOptions({scene: {backgroundType: "image",backgroundImage: "url(//data.mars3d.cn/img/busin…

telnet命令检查端口

1、简介 telnet是一种用于远程登录的协议&#xff0c;可以通过telnet客户端连接到远程主机&#xff0c;并在远程主机上执行命令。 2、使用telnet命令检查端口 2.1 进入linux终端 2.2 输入telnet命令 如果没有安装telnet命令&#xff0c;请执行以下命令安装 sudo yum install…