2018校招真题【牛客网】练习(二)

1、等差数列

题目描述:
如果一个数列S满足对于所有的合法的i,都有S[i + 1] = S[i] + d, 这里的d也可以是负数和零,我们就称数列S为等差数列。
小易现在有一个长度为n的数列x,小易想把x变为一个等差数列。小易允许在数列上做交换任意两个位置的数值的操作,并且交换操作允许交换多次。但是有些数列通过交换还是不能变成等差数列,小易需要判别一个数列是否能通过交换操作变成等差数列

思路:
重新排序,然后计算所有差值,如果相等就是等差,否则不是。

代码:

import java.util.*;
public class Main{
    public static void main(String[] args){
        Scanner scanner = new Scanner(System.in);
        int n = scanner.nextInt();
        int[] nums = new int[n];
        for(int i=0;i<n;i++){
            nums[i] = scanner.nextInt();
        }
        scanner.close();
        if(n<=2){
            System.out.println("Possible");
            return;
        }
        for(int i=0;i<n-1;i++){
            for(int j=i+1;j<n;j++){
                if(nums[i]>nums[j]){
                    int temp = nums[i];
                    nums[i] = nums[j];
                    nums[j] = temp;
                }
            }
        }
        int diff = nums[1]-nums[0];
        for(int i=1;i<n;i++){
            if(nums[i]-nums[i-1]!=diff){
                System.out.println("Impossible");
                return;
            }
        }
        System.out.println("Possible");
    }
}
2、交错10串

题目描述:
如果一个01串任意两个相邻位置的字符都是不一样的,我们就叫这个01串为交错01串。例如: “1”,“10101”,"0101010"都是交错01串。
小易现在有一个01串s,小易想找出一个最长的连续子串,并且这个子串是一个交错01串。小易需要你帮帮忙求出最长的这样的子串的长度是多少。

思路:
如果遇到相同字符,则比较之前的序列中最长的和现在的长度,取较长的那一个;如果不是相同字符,则当前字符长度+1。

代码:

import java.util.*;
public class Main{
    public static void main(String[] args){
        Scanner scanner = new Scanner(System.in);
        String input = scanner.nextLine();
        scanner.close();
        int len = 0;
        int maxlen = 0;
        char front = '2';
        for(int i=0;i<input.length();i++){
            if(input.charAt(i)!=front){
                len++;
            }else{
                maxlen = Math.max(len,maxlen);
                len = 1;
            }
            front = input.charAt(i);
        }
        maxlen = Math.max(len,maxlen);
        System.out.println(maxlen);
    }
}
3、操作序列

题目描述:
小易有一个长度为n的整数序列,a_1,…,a_n。然后考虑在一个空序列b上进行n次以下操作:
1、将a_i放入b序列的末尾
2、逆置b序列
小易需要你计算输出操作n次之后的b序列。

思路:
这个操作相当于,第i次插入的index为0和末尾交替。最后输出时考虑一下奇偶性,从头开始还是从尾开始即可。

代码:

import java.util.*;
public class Main{
    public static void main(String[] args){
        Scanner scanner = new Scanner(System.in);
        int n = scanner.nextInt();
        int[] nums = new int[n];
        for(int i=0;i<n;i++){
            nums[i] = scanner.nextInt();
        }
        scanner.close();
        ArrayList<Integer> b = new ArrayList<>();
        for(int i=0;i<n;i++){
            if(i%2==0){
                b.add(nums[i]);
            }else{
                b.add(0,nums[i]);
            }
        }
        if(n%2==0){
            for(int i=0;i<n-1;i++){
                System.out.print(b.get(i)+" ");
            }
            System.out.println(b.get(n-1));
        }else{
            for(int i=n-1;i>=1;i--){
                System.out.print(b.get(i)+" ");
            }
            System.out.println(b.get(0));
        }
    }
}
4、独立的小易

题目描述:
小易为了向他的父母表现他已经长大独立了,他决定搬出去自己居住一段时间。一个人生活增加了许多花费: 小易每天必须吃一个水果并且需要每天支付x元的房屋租金。当前小易手中已经有f个水果和d元钱,小易也能去商店购买一些水果,商店每个水果售卖p元。小易为了表现他独立生活的能力,希望能独立生活的时间越长越好,小易希望你来帮他计算一下他最多能独立生活多少天。

思路:
分两种情况:
1、已有水果没有吃完,房租用完所有钱
2、水果吃完,每天付款(房租+水果)

代码:

import java.util.*;
public class Main{
    public static void main(String[] args){
        Scanner scanner = new Scanner(System.in);
        int houseRent = scanner.nextInt();
        int leftFruit = scanner.nextInt();
        int leftMoney = scanner.nextInt();
        int fruitPrice = scanner.nextInt();
        scanner.close();
        if(leftFruit*houseRent>=leftMoney){
            System.out.println(leftMoney/houseRent);
        }else{
            int days = leftFruit;
            leftMoney -= (leftFruit*houseRent);
            days += (leftMoney/(houseRent+fruitPrice));
            System.out.println(days);
        }
    }
}
5、堆棋子

题目描述:
小易将n个棋子摆放在一张无限大的棋盘上。第i个棋子放在第x[i]行y[i]列。同一个格子允许放置多个棋子。每一次操作小易可以把一个棋子拿起并将其移动到原格子的上、下、左、右的任意一个格子中。小易想知道要让棋盘上出现有一个格子中至少有i(1 ≤ i ≤ n)个棋子所需要的最少操作次数.

思路:
参考讨论帖,链接:https://www.nowcoder.com/questionTerminal/27f3672f17f94a289f3de86b69f8a25b
用反证法,xy轴其实是独立的,先只考虑x坐标,假设把k个棋子堆到x0格子所用的步骤最少,a个棋子初始在x0的左边,b个棋子初始在x0的右边,且a>b,那么必然存在横坐标为x0-1的格子,这k个棋子到x0-1的步数会更少,b>a的情况,那么x0+1的目标将比x0更优,至于a=b,x0-1 和x0的步数是一样的。因此,最终汇聚棋子的x坐标只要在棋子初始的x个坐标中考虑

代码:

import java.util.*;
public class Main{
    public static void main(String[] args){
        Scanner scanner = new Scanner(System.in);
        int n = scanner.nextInt();
        int[] x = new int[n];
        int[] y = new int[n];
        for(int i=0;i<n;i++){
            x[i] = scanner.nextInt();
        }
        for(int i=0;i<n;i++){
            y[i] = scanner.nextInt();
        }
        scanner.close();
        for(int i=0;i<n;i++){
            if(i==n-1){
                System.out.println(minInstance(x,y,i+1,n));
            }else{
                System.out.print(minInstance(x,y,i+1,n)+" ");
            }
            
        }
    }
    
    public static int calculateInstance(int x1, int y1, int x2, int y2){
        return Math.abs(x1-x2)+Math.abs(y1-y2);
    }
    
    public static int minInstance(int[] x, int[] y, int size, int n){
        int result = Integer.MAX_VALUE;
        for(int i=0;i<n;i++){
            for(int j=0;j<n;j++){
                int total = 0;
                PriorityQueue<Integer> distances = new PriorityQueue<>(size,new Comparator<Integer>(){
                    @Override
                    public int compare(Integer o1, Integer o2){
                        return o2-o1;
                    }
                });
                // n个点的距离总和
                for(int k=0;k<n;k++){
                    int distance = calculateInstance(x[k],y[k],x[i],y[j]);
                    total+=distance;
                    distances.offer(distance);
                    // 减去n-size个点到这里的距离
                    if(distances.size()>size){
                        total-=distances.poll();
                    }
                }
                result = Math.min(result,total);
            }
        }
        return result;
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值