笔试-918-xhs

第二题

有一个包含 n 个不相同整数的数组 arr = [a[0], a[1], …, a[n-1]]。 你可以随意交换数组中的任意两个元素的位置。一个数组如果满足 在0 给到一个数组 arr , 计算并返回需要交换的最小次数,使得数组 arr 变为一个漂亮数组。
样例
arr = [7, 15, 12, 3]
arr 对应的一种漂亮数组为[3, 7, 12, 15]. 为了变换成这样的数组,需要做如下交换操作
[7, 15, 12, 3]
[3, 7, 12, 15]
共执行2次元素交换操作使得输入数组变换成漂亮数组,这是所需要的最少交换次数。

输入描述
第一行输入是一个整数 n, 标识输入数组的元素个数. 第二行输入包含n个用空格分割的整数arr[i]
输出描述
最小需要进行交换的次数

样例输入
4
2 5 3 1
样例输出
2

思路:根据贪心思路,漂亮数组一定是严格递增数组或严格递减数组。题目转化为:用最小的转化次数把数组变为严格单调的。
找环,比如3 2 5 4 1 想变成 1 2 3 4 5,这里的1 3 5形成了一个环,作为一组 repeat
2自成一组repeat,4自成一组repeat
最后的交换次数是数组长度减去repeat
代码:

import java.util.*;
public class Main {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        int n = sc.nextInt();
        int[] input = new int[n];
        int[] sorted = new int[n];
        for (int i = 0; i < n; i++) {
            input[i] = sc.nextInt();
            sorted[i] = input[i];
        }
        Arrays.sort(sorted);
        //全部数字正序的最小交换次数
        int increase = minSwapTimes(input, sorted);
        //开始反转数组
        int left = 0, right = sorted.length - 1;
        while (left < right) {
            int temp = sorted[left];
            sorted[left] = sorted[right];
            sorted[right] = temp;
            left++;
            right--;
        }
        //全部数字逆序的最小交换次数
        int decrease = minSwapTimes(input, sorted);
        System.out.println(Math.min(increase, decrease));
    }

    public static int minSwapTimes(int[] input, int[] sorted) {
        int n = input.length;
        Map<Integer, Integer> map = new HashMap<>();
        //用map记录每个元素排序后本来应该在的位置
        for (int i = 0; i < n; i++) {
            map.put(sorted[i], i);
        }
        //每多一个repeat就可以减少一次交换
        int repeat = 0;
        boolean[] visited = new boolean[n];//标记是否被访问过
        for (int i = 0; i < n; i++) {
            if (!visited[i]) {
                int j = i;
                while (!visited[j]) {
                    visited[j] = true;
                    j = map.get(input[j]);
                }
                repeat++;
            }
        }
        return n - repeat;
    }
}

第三题

薯队长最近迷上了写一种抽象诗,由于诗歌的意义对于抽象诗意义不大,薯队长想用非同寻常的词语组合打动读者。现在,他为未来的诗歌准备了N行诗句,不过他突然意识到这些诗并不押韵。
薯队长决定遵循古诗的押韵。诗歌被分为若干段,每段都是四行诗。每一句诗都有一个韵脚,假如A和B表示两种不同的韵脚,每段四行诗的韵脚只可能是 “AABB”, “ABAB”, “ABBA” 和“AAAA”中的一种。
薯队长现状将诗句的韵脚都编了号,具有相同编号的句子代表有相同的韵脚。现在,薯队长想删掉一些句子,使得剩下的都是遵循押韵规则的四行诗。
请帮薯队长找出满足条件最长的诗歌。当然了,是不能改变诗句的顺序的。

输入描述
数据第一行包括整数N(1<=N<=4000),代表诗歌的句子数。
接下来N个整数分别表示每一行诗的韵脚。这些数字都是不超过10^9的正数。
输出描述
一行一个整数k,为薯队长最多能够得到的四行诗个数。

样例输入
15
1 2 3 1 2 1 2 3 3 2 1 1 3 2 2
样例输出
3

样例说明
样例分成三段四行诗,分别为:
1 2 4 5
7 8 9 10
11 12 14 15

思路:

动态规划,dp[i]表示[1,i]内能得到的答案,枚举i,往前遍历找到第一个与a[i]相同的值,下标为mid,查询已经遍历的区间内有无另一个值的个数大于1,如果有,dp[i]=max(dp[i],dp[mid-1]+1),如果无,则继续往前遍历,找到第一个满足区间内a[i]的个数大于3或者不为a[i]的个数大于1的下标pos,则dp[i]=max(dp[i],dp[pos-1]+1),最后区dp[i]=max(dp[i],dp[i-1])。最终答案就是dp[n]。

你可能感兴趣的:(2022秋招,java)