【笔试面试真题】Java实现数列还原

2023-10-31

题目描述:
牛牛的作业薄上有一个长度为 n 的排列 A,这个排列包含了从1到n的n个数,但是因为一些原因,其中有一些位置(不超过 10 个)看不清了,但是牛牛记得这个数列顺序对的数量是 k,顺序对是指满足 i < j 且 A[i] < A[j] 的对数,请帮助牛牛计算出,符合这个要求的合法排列的数目。
输入描述:
每个输入包含一个测试用例。每个测试用例的第一行包含两个整数 n 和 k(1 <= n <= 100, 0 <= k <= 1000000000),接下来的 1 行,包含 n 个数字表示排列 A,其中等于0的项表示看不清的位置(不超过 10 个)。
输出描述:
输出一行表示合法的排列数目。

示例1
输入:
5 5
4 0 0 2 0
输出:
2


思路:
参考数列还原-回溯法,点击查看原文

首先提取一下关键信息:
1、排列A中的元素是唯一的,即每个数仅出现一次,不存在重复情况;
2、顺序对无关元素绝对位置,只需关注相对位置即可;
3、模糊数不超过10个,对于遍历的负担较小,可以使用穷举

那么我们需要考虑的就是模糊数所产生的顺序对k2,这个值应是排序A的总顺序对数量k减去已有元素产生的顺序对k1,即k2=k-k1。
另外还需要得到一个存储未使用数字的数组loss、存储模糊数位置的数组indexs。

然后就是将模糊数全排列,这里可以使用递归的方法,传入模糊数组的坐标index、未使用元素的坐标countIndex,与剩余未产生顺序对数量surplus(初始为k2)。

结束条件分为合法输入与非法输入:
合法输入指填充得到的完整排列顺序数与k相同;
非法输入指填充得到的完整排序顺序数与k不同。

使用一个循环将loss数组中的元素依次填入,并递归至下一位置,在填入后需要计算该元素填入该位置后产生的顺序对,计算方法如下(存储数列A的counts以定义为私有变量):

    //在index插入count后增加的顺序对
    public static int add(int index, int count){
        int sum = 0;
        for(int i = 0; i < index; i++){
            if(counts[i] != 0 && counts[i] < count)
                sum++;
        }
        for(int i = index; i < n; i++){
            if(counts[i] != 0 && counts[i] > count)
                sum++;
        }
        return sum;
    }

下一次递归的surplus=surplus-add(index,count)。
需要注意的是在递归后需要将该次填充位置的数还原,并将使用的填充数归还。

代码如下:

public static void recur(int index, int countIndex, long surplus){
        if(surplus == 0 && loss.size() == 0){
            //合法则通过
            result++;
            return;
        }
        if(surplus < 0 || countIndex >= loss.size()){
            //非法则返回
            return;
        }
        for(int i = 0; i < loss.size(); i++){
            int count = loss.remove(i);
            //填充
            counts[indexs.get(index)] = count;
            //下一位置
            recur(index+1, countIndex, surplus-add(indexs.get(index), count));
            //清除操作
            counts[indexs.get(index)] = 0;
            loss.add(i, count);
        }
    }

代码实现:

import java.util.*;
public class Main{
    //总数
    private static int n;
    //总顺序对
    private static long k;
    //数列
    private static int[] counts;
    //存储模糊数位置
    private static ArrayList<Integer> indexs = new ArrayList<>();
    //存储剩余可用数
    private static ArrayList<Integer> loss = new ArrayList<>();
    //存储数列
    private static HashSet<Integer> set = new HashSet<>();
    //结果
    private static int result;
    public static void main(String[] args){
        Scanner sc = new Scanner(System.in);
        while(sc.hasNext()){
            n = sc.nextInt();
            k = sc.nextLong();
            counts = new int[n];
            for(int i = 0; i < n; i++){
                counts[i] = sc.nextInt();
            }
            //分离数列
            for(int i = 0; i < n; i++){
                set.add(counts[i]);
                if(counts[i] == 0){
                    indexs.add(i);
                    continue;
                }
                for(int j = i+1; j < n; j++){
                    //去除已有顺序对
                    if(counts[j] > counts[i])
                        k--;
                }
            }
            //剩余可用数字
            for(int i = 1; i <= n; i++){
                if(!set.contains(i)){
                    loss.add(i);
                }
            }
            recur(0, 0, k);
            System.out.println(result);
        }
    }
    public static void recur(int index, int countIndex, long surplus){
        if(surplus == 0 && loss.size() == 0){
            //合法则通过
            result++;
            return;
        }
        if(surplus < 0 || countIndex >= loss.size()){
            //非法则返回
            return;
        }
        for(int i = 0; i < loss.size(); i++){
            int count = loss.remove(i);
            //填充
            counts[indexs.get(index)] = count;
            //下一位置
            recur(index+1, countIndex, surplus-add(indexs.get(index), count));
            //清除操作
            counts[indexs.get(index)] = 0;
            loss.add(i, count);
        }
    }
    //在index插入count后增加的顺序对
    public static int add(int index, int count){
        int sum = 0;
        for(int i = 0; i < index; i++){
            if(counts[i] != 0 && counts[i] < count)
                sum++;
        }
        for(int i = index; i < n; i++){
            if(counts[i] != 0 && counts[i] > count)
                sum++;
        }
        return sum;
    }
}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

【笔试面试真题】Java实现数列还原 的相关文章

随机推荐

  • Python3 pip

    Python3 pip pip 是 Python 包管理工具 该工具提供了对 Python 包的查找 下载 安装 卸载的功能 软件包也可以在 https pypi org 中找到 目前最新的 Python 版本已经预装了 pip 注意 Py
  • Nginx添加SSL模块

    目录 一 SSL 概述 SSL证书 HTTPS SSL工作原理 二 创建SSL证书 安装openssl 生成证书 三 nginx配置 nginx打补丁添加模块 nginx conf配置 四 访问 一 SSL 概述 SSL Security
  • 向日葵权限mac

    问题 权限打开后自动关上 解决 mac上几乎所有远程软件都会出现这种权限设置问题 换了腾讯会议或其他也没用 方法一 试试先打开系统的安全性设置 将向日葵软件从隐私框里移出来 点击 号移除 再重新添加进去 方法二 将权限的勾选去掉 再添加 然
  • EFCore 数据模型 和 值转换

    操作中经常要涉及到模型和值转换的问题 这里记录一下 实际使用过程中遇到过的问题 而非功能的全部 模型 EFCore中支持字段 参考地址 https docs microsoft com zh cn ef core modeling back
  • SpringBoot框架详解,实战入门教程

    SpringBoot作为当下Java开发最常用的技术框架 相信你也一定听过很多次了 那么到底什么是SpringBoot SpringBoot又有什么用呢 跟着动力节点的视频快速入门springboot 视频观看资源 https www bi
  • CIKM 2023|TASTE:通过文本匹配缓解序列化推荐中流行偏差问题

    序列化推荐系统旨在根据用户的浏览历史动态地为用户推荐下一个商品 这在Yelp TikTok Amazon等众多Web应用程序中发挥着至关重要的作用 这些推荐系统通过使用不同的神经网络架构来学习用户 商品交互中商品之间的依赖关系 从而对用户行
  • Qt:文管打开方式:选择并设置默认程序

    默认启动APP配置文件 local share applications mimeapps list config mimeapps list etc gnome defaults list 全局 QAction action choose
  • 整理一些spring常见的扩展点

    一 各种后处理器 1 1 BeanDefinition与BeanFactory扩展 1 1 1 BeanDefinitionRegistryPostProcessor接口 Extension to the standard link Bea
  • 解决Vue前端报错——Error: Cannot find module ‘node-sass‘

    解决Vue前端报错 Error Cannot find module node sass 今天在使用VsCode 导入一个新Vue項目文件夹的时候出现了以下的问题 npm run dev提示 Cannot find module node
  • Winform自定义表单(转)

    出处 http www newlifex com showtopic 167 aspx 好吧 附件真的损坏了 原始代码我也没有了 再提取我也没精力了 不好意思 哪位之前下过可以重发一遍吗 不过即使没有也可以参考下面几个示例很快就可以做出来了
  • docker容器二之Dockerfile详解+镜像的优化

    文章目录 Dockerfile详解 Dockerfile常用指令 Dockerfile示例 实验截图 解决报错 Shell和exec格式的区别 镜像的优化 Dockerfile详解 Dockerfile常用指令 首先先明白 什么是Docke
  • matlab/simulink scope 示波器添加菜单栏的方法

    在用matlab simulink scope 示波器的时候 弹出的图像框没有菜单栏 保存复制等操作极为不便 以下操作可以让示波器的图形窗口显示出菜单栏 在matlab的command window里执行下面两句代码 set 0 ShowH
  • 【华为OD机试】工号不够用了怎么办【2023 B卷

    华为OD机试 真题 点这里 华为OD机试 真题考点分类 点这里 题目描述 3020年 空间通信集团的员工人数突破20亿人 即将遇到现有工号不够用的窘境 现在 请你负责调研新工号系统 继承历史传统 新的工号系统由小写英文字母 a z 和数字
  • spring的ApplicationContext 得到方式

    ClassPathXmlApplicationContext会自己在CLASSes里面找 不过我只是把配置文件放在src文件下成功找到过 String paths applicationContextDataSource xml appli
  • MarkDown中写流程图的方法

    序 Mermaid FlowChat 中译为美人鱼 就好比一条美人鱼在流动构成了流程图 是一种在MarkDown中以特定格式的文字生成流程图或是图标的方法 一种简单的降价式脚本语言 用于通过javascript从文本生成图表 官方文档点这里
  • 【华为OD机试真题】94、猜密码

    文章目录 一 题目 题目描述 输入输出 样例1 二 代码与思路参考 C语言思路 C代码 C 语言思路 C 代码 Java语言思路 Java代码 Python语言思路 Python代码
  • 13-集合框架

    引言 集合框架 理解为集合体系指的是由很多类共同构成 这些类之间存在关系 继承或实现 是成体系的类和接口 一 认识集合 在java程序中 集合是存放数据的容器 它数组一样 但是但是 是存在差异的 从使用上说 集合更为方便 因为集合容量会随着
  • LTP--Linux Test Project

    简介 LTP套件是由 Linux Test Project 所开发的一套系统测试套件 它基于系统资源的利用率统计开发了一个测试的组合 为系统提供足够的压力 通过压力测试来判断系统的稳定性和可靠性 压力测试是一种破坏性的测试 即系统在非正常的
  • element upload限制图片上传格式

    限制图片的格式 html部分 点击选择图片的正常操作是只会出现图片格式 如果选择所有文件 我们就要重新进行验证 在选择照片的时候我们就要进行判断 所以是在on change事件中判断是否为照片格式 先封装一个isImage方法 isImag
  • 【笔试面试真题】Java实现数列还原

    题目描述 牛牛的作业薄上有一个长度为 n 的排列 A 这个排列包含了从1到n的n个数 但是因为一些原因 其中有一些位置 不超过 10 个 看不清了 但是牛牛记得这个数列顺序对的数量是 k 顺序对是指满足 i lt j 且 A i lt A