笔试复盘(3.6)

本文是对一场编程笔试的复盘,详细介绍了五个不同类型的题目:包括寻找最大不连续子集、翻转数组求最大子段和、切割豆腐求最大体积、数组区间操作和数字串推理游戏。每个题目都提供了题目的描述、输入输出示例以及解题思路。
摘要由CSDN通过智能技术生成

笔试复盘(3.6)

题目一
题目描述

小团最近在玩手机上的四川麻将。四川麻将的一种玩法是玩家摸完牌之后选择三张花色一样的牌按某种顺序换给其他人。为了尽可能破坏对手的游戏体验,小团每次都会选择不连续的三张牌换出去。比如小团手上有14568这5张条子,则他可能会选择158这三张条子换出去。爱思考的小团马上对这个问题进行了推广。
小团把这个问题进行了简化,现在他给了你一个可重集合,并希望你从中选出一个尽可能大的子集使得其中没有两个数是“连续”的(连续是指即这两个数之差的绝对值不超过1)。

输入描述

第一行有一个整数n(1<=n<=100000),代表小团给你的可重集大小。
第二行有n个空格隔开的整数(范围在1到200000之间),代表小团给你的可重集。

输出描述

输出满足条件的最大子集的大小。

样例输入

6
1 2 3 5 6 7

样例输出

4

思路:

简单理解题意,从给出的数字序列中得到一串不连续的数字序列,使序列中含元素尽可能多,如样例1 3 5 7便是最大的不连续数字序列。

由于给出的序列至少有一位数字,则第一个元素可以直接拿取,可以设置一个整型变量 pre 代表上一个拿取的元素,初始化为给出序列的第一个元素。

后续的序列贪心拿取即可,贪心拿取需要保证序列为有序。所以遍历前需要进行一次排序。

从第二个元素开始遍历所给序列,若与pre差值大于1,则更换pre值,继续选取下一个可选数字即可。

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

        int n;
        n= sc.nextInt();
        int[] arr=new int[n];
        Arrays.sort(arr);
        for(int i=0;i<n;i++) arr[i]=sc.nextInt();

        int ans=1;
        int pre=arr[0];
        for(int i=1;i<arr.length;i++){
   
            int dex=arr[i]-pre;
            if(dex>1){
   
                ans++;
                pre=arr[i];
            }
        }
        System.out.println(ans);

    }
}
题目二
题目描述

最大子段和是一个经典问题,即对于一个数组找出其和最大的子数组。
现在允许你在求解该问题之前翻转这个数组的连续一段(如翻转{1,2,3,4,5,6}的第三个到第五个元素组成的子数组得到的是{1,2,5,4,3,6}),则翻转后该数组的最大子段和最大能达到多少?

输入描述
第一行有一个正整数n(1<=n<=100000),代表数组长度。
第二行有n个空格隔开的整数(-1000<=ai<=1000),代表给出数组。

输出描述

输出一个整数,代表若允许你翻转一个子数组 ,则翻转后所得数组的最大子段和最大能到多少。

样例输入

6
-1 3 -5 2 -1 3

样例输出

7

思路:

解决一下如何求一个序列的最大子段和,力扣有最大子段和求解方式,可以利用动态规划解决。

状态表示为dp[i],表示以下标为i的元素结尾的序列的最大字段的和。

这样的话,最后只需要求出dp[0]~dp[n]中最大的值就是最大子段和了。

状态转移方程:

令给出的序列为a[0]~a[i],a[i]只有两种情况,与以a[i-1]结尾的最大子段结合;只保留自己,单独构成字段

若dp[i-1]<0,则a[i]自身构成字段显然字段和更大,dp[i]=a[i];反之dp[i]=dp[i-1]+a[i]

但是翻转位置的选择呢,我们枚举翻转位置即可,时间复杂度O(N*N)

源码如下:

class Solution22{
   
    public static void main(String[] args) {
   
        Scanner sc=new Scanner(System.in);
        int n=sc.nextInt();
        int[] nums=new int[n];
        for(int i=0;i<n
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值