石碑文字全排列重组(华为od机考题)

news2024/11/16 7:33:29

一、题目

1.原题

有一个考古学家发现一个石碑,
但是很可惜,发现时其已经断成多段,
原地发现n个断口整齐的石碑碎片。
为了破解石碑内容,
考古学家希望有程序能帮忙计算复原后的石碑文字组合数,
你能帮忙吗?
[递归, 字符串, 哈希表]

2.题目理解

有n个碎片(字符可能重复),对这些碎片进行全排列然后输出。

二、思路与代码过程

1.思路

递归 回溯

2.代码过程

①main函数

public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        System.out.println("请输入碎片的块数n:");
        int n = sc.nextInt();
        System.out.println("请依次输入碎片上的文字:");
        sc.nextLine();
        String[] words = sc.nextLine().split(" ");

        long factorial = factorial(n);
        System.out.println("当前碎片有"+factorial+"种排列方式");
        Arrays.sort(words);  // 排序以处理重复元素

        ArrayList<String> reStrings = new ArrayList<>();
        StringBuilder reString = new StringBuilder();
        boolean[] used = new boolean[n];
        ArrayList<String> ReStrings = BackTrack(reStrings, reString, words, used);
        for (String s : ReStrings) {
            System.out.println(s);
        }
    }

②数量计算(写来好玩的)

//计算阶乘
    public static long factorial(int n) {
        return LongStream.rangeClosed(1, n)
                .reduce(1, (a, b) -> a * b);
    }

③BackTrack函数

private static ArrayList<String> BackTrack
            (ArrayList<String> reStrings, StringBuilder reString,
             String[] words, boolean[] used) {
        if (reString.toString().split(" ").length == words.length) {
            reStrings.add(reString.toString().trim());  // 去掉末尾的空格
        } else {
            for (int i = 0; i < words.length; i++) {
                if (used[i]) continue;
                if (i > 0 && words[i].equals(words[i - 1]) && !used[i - 1]) continue;

                reString.append(words[i]).append(" ");
                used[i] = true;

                BackTrack(reStrings, reString, words, used);

                // 回溯
                reString.setLength(reString.length() - words[i].length() - 1);  // 1 for space
                used[i] = false;
            }
        }
        return reStrings;
    }

三、运行结果

1.运行截图

2.带数据分析运行结果

请输入碎片的块数n:
3
请依次输入碎片上的文字:
i o u
当前碎片有6种排列方式
-----------------BackTrack Start------------------
正在组合哦!
当前i为:0,word为:i,使用状况为:false
组合中,当前i为:i
组合后,当前reString为:i 
=======进入回溯啦======
-----------------BackTrack Start------------------
正在组合哦!
当前i为:0,word为:i,使用状况为:true
当前i:i被用过啦!
当前i为:1,word为:o,使用状况为:false
组合中,当前i为:o
组合后,当前reString为:i o 
=======进入回溯啦======
-----------------BackTrack Start------------------
正在组合哦!
当前i为:0,word为:i,使用状况为:true
当前i:i被用过啦!
当前i为:1,word为:o,使用状况为:true
当前i:o被用过啦!
当前i为:2,word为:u,使用状况为:false
组合中,当前i为:u
组合后,当前reString为:i o u 
=======进入回溯啦======
-----------------BackTrack Start------------------
完成了一条组合:i o u
当前reStrings为:[i o u]
-----------------BackTrack End------------------
=======回溯完成啦======
撤销后当前的reString为:i o 
-----------------BackTrack End------------------
=======回溯完成啦======
撤销后当前的reString为:i 
当前i为:2,word为:u,使用状况为:false
组合中,当前i为:u
组合后,当前reString为:i u 
=======进入回溯啦======
-----------------BackTrack Start------------------
正在组合哦!
当前i为:0,word为:i,使用状况为:true
当前i:i被用过啦!
当前i为:1,word为:o,使用状况为:false
组合中,当前i为:o
组合后,当前reString为:i u o 
=======进入回溯啦======
-----------------BackTrack Start------------------
完成了一条组合:i u o
当前reStrings为:[i o u, i u o]
-----------------BackTrack End------------------
=======回溯完成啦======
撤销后当前的reString为:i u 
当前i为:2,word为:u,使用状况为:true
当前i:u被用过啦!
-----------------BackTrack End------------------
=======回溯完成啦======
撤销后当前的reString为:i 
-----------------BackTrack End------------------
=======回溯完成啦======
撤销后当前的reString为:
当前i为:1,word为:o,使用状况为:false
组合中,当前i为:o
组合后,当前reString为:o 
=======进入回溯啦======
-----------------BackTrack Start------------------
正在组合哦!
当前i为:0,word为:i,使用状况为:false
组合中,当前i为:i
组合后,当前reString为:o i 
=======进入回溯啦======
-----------------BackTrack Start------------------
正在组合哦!
当前i为:0,word为:i,使用状况为:true
当前i:i被用过啦!
当前i为:1,word为:o,使用状况为:true
当前i:o被用过啦!
当前i为:2,word为:u,使用状况为:false
组合中,当前i为:u
组合后,当前reString为:o i u 
=======进入回溯啦======
-----------------BackTrack Start------------------
完成了一条组合:o i u
当前reStrings为:[i o u, i u o, o i u]
-----------------BackTrack End------------------
=======回溯完成啦======
撤销后当前的reString为:o i 
-----------------BackTrack End------------------
=======回溯完成啦======
撤销后当前的reString为:o 
当前i为:1,word为:o,使用状况为:true
当前i:o被用过啦!
当前i为:2,word为:u,使用状况为:false
组合中,当前i为:u
组合后,当前reString为:o u 
=======进入回溯啦======
-----------------BackTrack Start------------------
正在组合哦!
当前i为:0,word为:i,使用状况为:false
组合中,当前i为:i
组合后,当前reString为:o u i 
=======进入回溯啦======
-----------------BackTrack Start------------------
完成了一条组合:o u i
当前reStrings为:[i o u, i u o, o i u, o u i]
-----------------BackTrack End------------------
=======回溯完成啦======
撤销后当前的reString为:o u 
当前i为:1,word为:o,使用状况为:true
当前i:o被用过啦!
当前i为:2,word为:u,使用状况为:true
当前i:u被用过啦!
-----------------BackTrack End------------------
=======回溯完成啦======
撤销后当前的reString为:o 
-----------------BackTrack End------------------
=======回溯完成啦======
撤销后当前的reString为:
当前i为:2,word为:u,使用状况为:false
组合中,当前i为:u
组合后,当前reString为:u 
=======进入回溯啦======
-----------------BackTrack Start------------------
正在组合哦!
当前i为:0,word为:i,使用状况为:false
组合中,当前i为:i
组合后,当前reString为:u i 
=======进入回溯啦======
-----------------BackTrack Start------------------
正在组合哦!
当前i为:0,word为:i,使用状况为:true
当前i:i被用过啦!
当前i为:1,word为:o,使用状况为:false
组合中,当前i为:o
组合后,当前reString为:u i o 
=======进入回溯啦======
-----------------BackTrack Start------------------
完成了一条组合:u i o
当前reStrings为:[i o u, i u o, o i u, o u i, u i o]
-----------------BackTrack End------------------
=======回溯完成啦======
撤销后当前的reString为:u i 
当前i为:2,word为:u,使用状况为:true
当前i:u被用过啦!
-----------------BackTrack End------------------
=======回溯完成啦======
撤销后当前的reString为:u 
当前i为:1,word为:o,使用状况为:false
组合中,当前i为:o
组合后,当前reString为:u o 
=======进入回溯啦======
-----------------BackTrack Start------------------
正在组合哦!
当前i为:0,word为:i,使用状况为:false
组合中,当前i为:i
组合后,当前reString为:u o i 
=======进入回溯啦======
-----------------BackTrack Start------------------
完成了一条组合:u o i
当前reStrings为:[i o u, i u o, o i u, o u i, u i o, u o i]
-----------------BackTrack End------------------
=======回溯完成啦======
撤销后当前的reString为:u o 
当前i为:1,word为:o,使用状况为:true
当前i:o被用过啦!
当前i为:2,word为:u,使用状况为:true
当前i:u被用过啦!
-----------------BackTrack End------------------
=======回溯完成啦======
撤销后当前的reString为:u 
当前i为:2,word为:u,使用状况为:true
当前i:u被用过啦!
-----------------BackTrack End------------------
=======回溯完成啦======
撤销后当前的reString为:
-----------------BackTrack End------------------
i o u
i u o
o i u
o u i
u i o
u o i

3.带数据分析完整代码

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Scanner;
import java.util.stream.LongStream;

public class test36 {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        System.out.println("请输入碎片的块数n:");
        int n = sc.nextInt();
        System.out.println("请依次输入碎片上的文字:");
        sc.nextLine();
        String[] words = sc.nextLine().split(" ");

        long factorial = factorial(n);
        System.out.println("当前碎片有"+factorial+"种排列方式");
        Arrays.sort(words);  // 排序以处理重复元素

        ArrayList<String> reStrings = new ArrayList<>();
        StringBuilder reString = new StringBuilder();
        boolean[] used = new boolean[n];
        ArrayList<String> ReStrings = BackTrack(reStrings, reString, words, used);
        for (String s : ReStrings) {
            System.out.println(s);
        }
    }
    //计算阶乘
    public static long factorial(int n) {
        return LongStream.rangeClosed(1, n)
                .reduce(1, (a, b) -> a * b);
    }
    private static ArrayList<String> BackTrack
            (ArrayList<String> reStrings, StringBuilder reString,
             String[] words, boolean[] used) {
        System.out.println("-----------------BackTrack Start------------------");

        if (reString.toString().split(" ").length == words.length) {
            System.out.println("完成了一条组合:"+reString.toString().trim());//
            reStrings.add(reString.toString().trim());  // 去掉末尾的空格
            System.out.println("当前reStrings为:" +reStrings);//
        } else {
            System.out.println("正在组合哦!");//
            for (int i = 0; i < words.length; i++) {
                System.out.println("当前i为:"+i+",word为:"+words[i]+",使用状况为:"+used[i]);//
                if (used[i]){
                    System.out.println("当前i:"+words[i]+"被用过啦!");//
                    continue;
                }
                if (i > 0 && words[i].equals(words[i - 1]) && !used[i - 1]){//处理重复
                    System.out.println("当前i为:"+words[i]+"和前面的重复啦,跳过哦!");
                    continue;
                }
                System.out.println("组合中,当前i为:"+words[i]);//
                reString.append(words[i]).append(" ");
                System.out.println("组合后,当前reString为:"+reString);//
                used[i] = true;
                System.out.println("=======进入回溯啦======");
                BackTrack(reStrings, reString, words, used);
                System.out.println("=======回溯完成啦======");
                // 回溯
                reString.setLength(reString.length() - words[i].length() - 1);  // 1 for space
                System.out.println("撤销后当前的reString为:"+reString);
                used[i] = false;
            }
        }
        System.out.println("-----------------BackTrack End------------------");
        return reStrings;
    }
}

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

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

相关文章

C# 三种定时器的用法

目录 1.System.Timers.Timer 2.System.Windows.Forms.Timer 3.System.Threading.Timer 4.简单的封装 这里介绍三种常用的定时器&#xff0c;方便查阅资料或直接复制使用。 1.System.Timers.Timer System.Timers.Timer 类定义了一个计时器&#xff0c;该计时器按固定间隔触…

大二必做项目贪吃蛇超详解之上篇win32库介绍

文章目录 1. 游戏背景2. 游戏效果演示3. 项目目标4. 前置知识5. Win32 API5. 1 控制台程序(Console)5. 2 控制台屏幕上的坐标 COORD5. 3 GetStdHandle5. 4 GetConsoleCursorlnfo5. 4. 1 CONSOLE_CURSOR_INFO5. 4. 2 SetConsoleCursorlnfo 5. 5 SetconsoleCursorPosition5. 6 Ge…

“汤姆猫除了不会捉杰瑞啥都会”之作为Web服务器,tomcat的常用部署方式 (Tomcat+memcached实现高可用)

目录 企业级WEB应用服务器TOMCAT一、tomcat的功能介绍1.1 安装 Tomcat1.2 tomcat的文件结构和组成1.3 生成tomcat的启动文件 二、结合反向代理实现tomcat部署2.1 常见部署方式介绍2.2 利用 nginx 反向代理实现2.3 实现tomcat中的负载均衡2.3.1 HTTP的无状态&#xff0c;有连接和…

Linux驱动学习之中断与等待队列

本篇分为设备树部分和API接口部分 设备树 想要使用中断&#xff0c;设备树中需要有两个属性&#xff1a; interrupts // 表示要使用哪一个中断, 中断的触发类型等等。 interrupt-parent // 这个中断要接到哪一个设备去? 即父中断控制器是谁 父中…

一种更快成像的新技术

斯旺西大学&#xff08;Swansea University&#xff09;的研究人员为中性原子束显微镜创造了一种新的成像方法&#xff0c;可大大加快显微镜图像的获取速度。中性原子束显微镜已成为科学研究的一个重点&#xff0c;因为它能够对商用显微镜无法成像的表面进行成像&#xff0c;例…

mysql集群从零开始搭建

文章目录 MySQL集群linux下部署mysqlmysql主从复制master配置配置slave新的slave加入延迟复制慢查询多线程原理 半同步模式原理gat模式启动半同步模式 mysql高可用之组复制&#xff08;MGR&#xff09;实现mysql组复制 mysql路由具体实现 mysql高可用之MHAMHA部署实施安装MHA软…

Codeforces Round 968 (Div. 2 ABCD1D2题) 视频讲解

A. Turtle and Good Strings Problem Statement Turtle thinks a string s s s is a good string if there exists a sequence of strings t 1 , t 2 , … , t k t_1, t_2, \ldots, t_k t1​,t2​,…,tk​ ( k k k is an arbitrary integer) such that: k ≥ 2 k \ge 2 k≥…

接口自动化测试利器,使用Rest Assured进行REST API测试

我们在做接口测试时&#xff0c;一般在代码中会使用HttpClient&#xff0c;但是HttpClient相对来讲还是比较麻烦的&#xff0c;代码量也相对较多&#xff0c;对于新手而言上手会比较难一点&#xff0c;今天我们来看下另一个接口测试工具包REST Assured REST Assured是一个流行…

Blazor官方文档学习记录

Blazor官方文档学习记录 1 官方文档2 Blazor教程-生成首个应用3 项目结构4 基础知识4.1 生态4.2 Razor组件指令顺序4.3 Razor组件的初始化方法 5 注意 1 官方文档 https://dotnet.microsoft.com/zh-cn/apps/aspnet/web-apps/blazor2 Blazor教程-生成首个应用 https://dotnet.…

Python | Linux | 解析Himawari-8/9 | Standard Data

写作前面 之前一个相关的工作需要解析Himawari-8/9 Standard Data文件&#xff0c;因为他是二进制的&#xff0c;之前没有处理过&#xff0c;导致完全摸不着头脑。在网上找了中英文搜索找了好久&#xff0c;虽然也找到了公开的解析代码&#xff0c;但是放在自己的数据这感觉总是…

趣味算法------猴子吃桃(循环,递归双重解法)

题目描述 猴子第一天摘下若干个桃子&#xff0c;当天吃了一半&#xff0c;后面又多吃一个。第二天早上又将剩下的桃子吃掉一半&#xff0c;又多吃了一个。后面每天猴子都吃了前一天剩下的一半零一个。到第十天想再吃时&#xff0c;只剩下一个桃子。求第一天共摘了多少桃子。 …

鸿蒙(API 12 Beta3版)【获取音视频元数据】音频播放与录制

使用AVMetadataExtractor可以实现从原始媒体资源中获取元数据&#xff0c;本开发指导将以获取一个音频资源的元数据作为示例&#xff0c;向开发者讲解AVMetadataExtractor元数据相关功能。视频资源的元数据获取流程与音频类似&#xff0c;由于视频没有专辑封面&#xff0c;所以…

【中仕公考怎么样】公务员备考小建议

2025年国考在即&#xff0c;掌握正确的备考方法很重要&#xff01;中仕为大家简单分享4点小技巧。 1. 在提升行测分数时&#xff0c;可以采用大量的练习题、整理题以及关注往年核心考点的方式。无论处于准备过程的哪一阶段&#xff0c;对各类题型进行深入分析并掌握相应的解题…

C++ | Leetcode C++题解之第373题查找和最小的K对数字

题目&#xff1a; 题解&#xff1a; class Solution { public:vector<vector<int>> kSmallestPairs(vector<int>& nums1, vector<int>& nums2, int k) {int m nums1.size();int n nums2.size();auto count [&](int target){long long …

怎么用AI生成PPT演讲稿?5个方法教你快速生成

想象一下&#xff0c;你正在准备一场关于“墨西哥是如何走到今天这一步的”演讲&#xff0c;而你却苦于如何将复杂的历史背景、经济变迁以及文化特色等内容有机地整合进一份PPT中。 这时候&#xff0c;一款好的AI自动生成PPT的工具就能派上用场了。它不仅能够帮助你快速构建起…

C# 使用 WinForm MDI 模式管理多个子窗体程序的详细步骤

前言 嗨&#xff0c;各位码农们&#xff01;今天我们要来聊聊如何在 C# 的 WinForms 应用程序中用 MDI&#xff08;Multiple Document Interface&#xff09;模式来优雅地管理多个子窗体。 如果你曾经对着一堆乱七八糟的窗体不知所措&#xff0c;或者想要让你的应用程序看起来…

基于SpringBoot的线上教学平台系统

你好呀&#xff0c;我是计算机学姐码农小野&#xff01;如果有相关需求&#xff0c;可以私信联系我。 开发语言 Java 数据库 MySQL 技术 SpringBoot框架&#xff0c;Java语言 工具 IDEA/Eclipse、Navicat、Maven 系统展示 首页 管理员功能模块 学员功能模块 前台首页…

16行为型设计模式——策略模式

一、策略模式简介 策略模式&#xff08;Strategy Pattern&#xff09;是一种行为型设计模式&#xff0c;它定义了一系列的算法&#xff0c;将每一个算法封装起来&#xff0c;并使它们可以相互替换。具体的算法选择交由客户端决定&#xff0c;即不同的算法可以在运行时动态地&a…

后端微服务架构:构建分布式博客系统

后端微服务架构&#xff1a;构建分布式博客系统 在当今的软件开发领域&#xff0c;微服务架构已经成为构建可扩展、灵活且易于维护的应用程序的主流选择。本文将探讨如何利用微服务架构来设计和实现一个分布式的博客系统。 1. 微服务架构简介 微服务架构是一种将应用程序分解…

练习题 期望dp

题目 分析&#xff1a; 首先注意到期望有线性性&#xff1a; E ( a b ) E ( a ) E ( b ) E(ab)E(a)E(b) E(ab)E(a)E(b)&#xff0c;其中 a a a、 b b b不要求相互独立。 因为网上很多地方的证明不严谨&#xff0c;所以这里证明一下&#xff1a; E ( a b ) ∑ i i ⋅ P …