【科大讯飞真题】科大讯飞0813秋招笔试真题 <模拟、哈希、双指针>

14 篇文章 0 订阅
12 篇文章 0 订阅

最大优美排列 <模拟>

小红认为一个排列是优美的,当且仅当对于任意i∈[1,n] , ai=n-ai+1成立,其中 n 代表排列的长度,ai 表示排列的第 i 个元素。她想知道 1-n 的所有优美排列中,字典序最大的是哪一个?注意,排列的定义为,若长度为 n 的序列中,1 到 n 都出现过且仅出现一次,则称该序列为一个排列。
输入描述
一个正整数n(1<=n<=10^5),代表排列的长度。
输出描述
一行n个正整数,用空格隔开。代表字典序最大的优美排列。

示例输入

2

输出

2 1

题解

import java.util.Scanner;

public class Main {
    public static void main(String[] args) {
        Scanner in = new Scanner(System.in);
        
        int n = in.nextInt();
        while (n > 0) {
            System.out.print(n-- + " ");
        }
    }
}

小红走字符串 <模拟>

小红有一个长度为n字符串s,他需要从第 1 个字符走到第n个字符,他每次只能走到相邻的字符。当他从si走到si+1时,他会消耗si+1-si点体力值。si+1-si若是负数,意味着他将恢复|si+1-si|点体力值,若体力值消耗到小于 0,则小红将无法继续走。字符相减时字符’a’代表 1,字符’b’代表 2…以此类推。已知小红现在有k点体力值,他能否从s1走到sn。若能走到,请输出他的剩余体力值,否则输出 -1。
输入描述
第一行两个整数n,k(1<=n,k<=10^5)。 第二行一个长度为n字符串s.
输出描述
一行一个整数,表示他的剩余体力值。若无法走到,则输出 -1。

输入

5 2
abcca

输出

2

说明
初始处理第一个字符时,体力值为2。
处理第二个字符时,体力值为1。
处理第三个字符时,体力值为0。
处理第四个字符时,体力值为0。
处理第五个字符时,体力值为2。
最终输出2

示例2
输入输出示例仅供调试,后台判题数据一般不包含示例

输入

5 1
abcca

输出

-1

题解

import java.util.*;

public class Main {
    public static void main(String[] args) {
        Scanner in = new Scanner(System.in);
        int n = in.nextInt();
        int k = in.nextInt();

        in.nextLine();

        char[] cs = in.nextLine().toCharArray();

        int index = 1;
        while (index < n) {
            if (k < cs[index] - cs[index - 1]) {
                System.out.println(-1);
                return;
            }
            k -= cs[index] - cs[index - 1];
            index++;
        }
        System.out.println(k);
    }
}

科大讯飞机器存储问题 <哈希、双指针>

智能语音、自然语言理解是科大讯飞较核心的技术、且保持在了世界前沿水平。在自然语言理解中,自然语言处理(nlp)为一个常见的技术,本题的具体场景也和这个技术相关。自然语言处理(nlp)经常会需要解决一些字符串的子串问题。我们把它抽象为数组的连续子数组问题。当处理一个数组时,机器会存储数组的一些连续子数组。不过为了节省存储空间,当机器遇到多个完全相同的连续子数组时只会存储一次。现在有一个棘手的问题,给定了两个长度为n的数组,这两个数组均满足以下性质:1 到n恰好出现了一次,请你判断机器存储完所有的连续子数组时,一共存储了多少次。

输入描述
第一行输入一个正整数n,代表数组的长度。
第二行输入n个正整数ai,代表第一个数组。
第三行输入n个正整数bi,代表第二个数组。
1<=n<=2* 1 0 5 10^5 105

输出描述
机器存储的次数。

示例1
输入

3
1 2 3
2 3 1

输出

8

说明
[1],[2],[3],[1,2],[2,3],[3,1],[1,2,3],[2,3,1] 一共存储了8次。

题解
对于两个子数组,最多需要存(1 + n) * n次,然后减去重复的次数。重复次数的计算,利用哈希表+双指针。

import java.util.Scanner;

public class Main {
    public static void main(String[] args) {
        Scanner in = new Scanner(System.in);
        int n = in.nextInt();


        int[] nums1 = new int[n];
        int[] nums2 = new int[n];
        int[] mpa = new int[n + 1];
        int[] mpb = new int[n + 1];

        for (int i = 0; i < n; i++) {
            nums1[i] = in.nextInt();
            //保存哈希
            mpa[nums1[i]] = i;
        }
        for (int i = 0; i < n; i++) {
            nums2[i] = in.nextInt();
            //保存哈希
            mpb[nums2[i]] = i;
        }

        //最多需要存(1 + n) * n次
        long res = (long) (1 + n) * n;
        for (int i = 0; i < n; i++) {
            //找一个数组中同一个数在俩个数组出现的位置
            int posa = mpa[nums1[i]];
            int posb = mpb[nums1[i]];

            int numSame = 0;
            //如果相等,继续往后查,还相等加 1
            while (posa < n && posb < n && nums1[posa] == nums2[posb]) {
                numSame++;
                posa++;
                posb++;
            }
            //减去重复的
            res -= numSame;
        }
        System.out.println("ans: "+res);
    }
}

暴力(使用Map或者Set存所有出现组合):

public class Main {
    public static void main(String[] args) {
        Scanner in = new Scanner(System.in);
        int n = in.nextInt();
        int[] nums1 = new int[n];
        int[] nums2 = new int[n];

        for (int i = 0; i < n; i++) {
            nums1[i] = in.nextInt();
        }
        for (int i = 0; i < n; i++) {
            nums2[i] = in.nextInt();
        }

        Map<String, String> resultMap = new LinkedHashMap<>();

        for (int i = 0; i < nums1.length; i++) {
            String s = "";
            for (int j = i; j < nums1.length; j++) {
                s += nums1[j] + "-";
                if (!resultMap.containsKey(s)) {
                    resultMap.put(s, s);
                }
            }
        }

        for (int i = 0; i < nums2.length; i++) {
            String s = "";
            for (int j = i; j < nums2.length; j++) {
                s += nums2[j] + "-";
                if (!resultMap.containsKey(s)) {
                    resultMap.put(s, s);
                }
            }
        }
        System.out.println(resultMap.size());
    }
}
public class Main {
    public static void main(String[] args) {
        Scanner in = new Scanner(System.in);
        int n = in.nextInt();
        int[] nums1 = new int[n];
        int[] nums2 = new int[n];

        for (int i = 0; i < n; i++) {
            nums1[i] = in.nextInt();
        }
        for (int i = 0; i < n; i++) {
            nums2[i] = in.nextInt();
        }
        //Map<String, String> resultMap = new LinkedHashMap<>();
        Set<String> resultSet = new HashSet<>();

        for (int i = 0; i < nums1.length; i++) {
            String s = "";
            for (int j = i; j < nums1.length; j++) {
                s += nums1[j] + "-";
                if (!resultSet.contains(s)) {
                    resultSet.add(s);
                }
            }
        }

        for (int i = 0; i < nums2.length; i++) {
            String s = "";
            for (int j = i; j < nums2.length; j++) {
                s += nums2[j] + "-";
                if (!resultSet.contains(s)) {
                    resultSet.add(s);
                }
            }
        }
        System.out.println(resultSet.size());
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Koma_zhe

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值