(C卷,200分)- 考古学家(Java & JS & Python)

题目描述

有一个考古学家发现一个石碑,但是很可惜,发现时其已经断成多段,原地发现n个断口整齐的石碑碎片。

为了破解石碑内容,考古学家希望有程序能帮忙计算复原后的石碑文字组合数,你能帮忙吗?

输入描述

第一行输入 n

  • n表示石碑碎片的个数

第二行依次输入石碑碎片上的文字内容s,共有n组。 

输出描述

输出石碑文字的组合(按照升序排列),行末无多余空格。

备注

如果存在石碑碎片内容完全相同,则由于碎片间的顺序变换不影响复原后的碑文内容,即相同碎片间的位置变换不影响组合。

用例

输入 3
a b c
输出 abc
acb
bac
bca
cab
cba
说明 当石碑碎片上的内容为“a”,“b”,“c”时,则组合有“abc”,“acb”,“bac”,“bca”,“cab”,“cba”
输入 3
a b a
输出 aab
aba
baa
说明 当石碑碎片上的内容为“a”,“b”,“a”时,则可能的组合有“aab”,“aba”,“baa”
输入 3
a b ab
输出 aabb
abab
abba
baab
baba
说明 当石碑碎片上的内容为“a”,“b”,“ab”时,则可能的组合有“aabb”,“abab”,“abba”,“baab”,“baba”

 

题目解析

本题是全排列求解问题。

关于全排列的求解可以看下:

关于不重复的全排列求解可以看下:

LeetCode – 47 全排列 II_leetcode 全排列2-CSDN博客

本题和leetcode47区别在于:

石碑碎片内容可能是多个字母,比如用例3:

此时树层去重是无法检测出来的,因此我们还需要对求出来的全排列字符串进行一次去重

JS算法源码

const rl = require("readline").createInterface({ input: process.stdin });
var iter = rl[Symbol.asyncIterator]();
const readline = async () => (await iter.next()).value;

void (async function () {
  // 输入获取
  const n = parseInt(await readline());
  const arr = (await readline()).split(" ");

  const res = new Set();
  const used = new Array(n).fill(false);
  const path = [];

  // 排序是为了让相同元素相邻,方便后面树层去重
  arr.sort();
  dfs(arr, used, path, res);

  // 输出石碑文字的组合(按照升序排列)
  [...res].sort().forEach((val) => console.log(val));
})();

function dfs(arr, used, path, res) {
  if (path.length == arr.length) {
    res.add(path.join(""));
    return;
  }

  for (let i = 0; i < arr.length; i++) {
    if (used[i]) continue;

    // 树层去重
    if (i > 0 && arr[i] == arr[i - 1] && !used[i - 1]) continue;

    path.push(arr[i]);
    used[i] = true;
    dfs(arr, used, path, res);
    used[i] = false;
    path.pop();
  }
}

Java算法源码

import java.util.Arrays;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.Scanner;

public class Main {
  static int n;
  static String[] arr;

  public static void main(String[] args) {
    Scanner sc = new Scanner(System.in);

    n = Integer.parseInt(sc.nextLine());
    arr = sc.nextLine().split(" ");

    getResult();
  }

  public static void getResult() {
    // 排序是为了让相同元素相邻,方便后面树层去重
    Arrays.sort(arr);

    boolean[] used = new boolean[n];
    LinkedList<String> path = new LinkedList<>();
    HashSet<String> res = new HashSet<>();

    dfs(used, path, res);

    // 输出石碑文字的组合(按照升序排列)
    res.stream().sorted(String::compareTo).forEach(System.out::println);
  }

  public static void dfs(boolean[] used, LinkedList<String> path, HashSet<String> res) {
    if (path.size() == n) {
      StringBuilder sb = new StringBuilder();
      path.forEach(sb::append);
      res.add(sb.toString());
      return;
    }

    for (int i = 0; i < n; i++) {
      if (used[i]) continue;

      // 树层去重
      if (i > 0 && arr[i].equals(arr[i - 1]) && !used[i - 1]) continue;

      path.addLast(arr[i]);
      used[i] = true;
      dfs(used, path, res);
      used[i] = false;
      path.removeLast();
    }
  }
}

Python算法源码

# 输入获取
n = int(input())
arr = input().split()


# 全局变量
path = []
used = [False] * n
cache = set()


# 全排列求解
def dfs():
    if len(path) == n:
        cache.add("".join(path))
        return

    for i in range(n):
        if used[i]:
            continue

        # 树层去重
        if i > 0 and arr[i] == arr[i-1] and not used[i-1]:
            continue

        path.append(arr[i])
        used[i] = True
        dfs()
        used[i] = False
        path.pop()


# 算法入口
def getResult():
    # 排序是为了让相同元素相邻,方便后面树层去重
    arr.sort()
    dfs()

    # 输出石碑文字的组合(按照升序排列)
    for v in sorted(list(cache)):
        print(v)


# 算法调用
getResult()

免责声明:

1、IT资源小站为非营利性网站,全站所有资料仅供网友个人学习使用,禁止商用
2、本站所有文档、视频、书籍等资料均由网友分享,本站只负责收集不承担任何技术及版权问题
3、如本帖侵犯到任何版权问题,请立即告知本站,本站将及时予与删除下载链接并致以最深的歉意
4、本帖部分内容转载自其它媒体,但并不代表本站赞同其观点和对其真实性负责
5、一经注册为本站会员,一律视为同意网站规定,本站管理员及版主有权禁止违规用户
6、其他单位或个人使用、转载或引用本文时必须同时征得该帖子作者和IT资源小站的同意
7、IT资源小站管理员和版主有权不事先通知发贴者而删除本文

0

评论0

站点公告

没有账号?注册  忘记密码?