java笔试-广联达2021秋招提前批java开发笔试

太菜了,暴力解法的结果居然不对…
后来写的,下面的代码没有经过OJ,思路应该是对的。

1.平行四边形构造

给出n个值,选出4个值组成面积最大得平行四边形。
输入:

5
3 3 4 4 5

输出:

12

思路:
要组成平行四边形,至少要有两组相同的值,例如2 2 3 3。
先把输入N个数的数组排序,然后找出出现过两次且最大的两个数,进行乘积。

import java.util.Arrays;
import java.util.Scanner;

/**
 * @author liu
 * @Description
 */
public class Main2 {
    public static void main(String[] args) {
    	//输入N
        Scanner ss1 = new Scanner(System.in);
        int N = ss1.nextInt();
		//连续输入N个数,存入数组
        int[] a=new int[N];
        for (int i=0;i<N;i++) {
            a[i] = ss1.nextInt();
        }
		//排序+遍历
        System.out.println(fun(a));

    }
	
	//排序后找出重复且最大的两个数
    private static int fun(int[] arr) {
        Arrays.sort(arr);
        int i = 0;
        int max = 1;//面积
        //找出出现过两次且最大的两个数
        for (int j = arr.length - 1; j >= 1; j--) {
            if (arr[j] == arr[j - 1]) {
                max = max * arr[j];
                j = j - 1;
                i++;
                if (i == 2) break;
            }
        }
        if (i < 2) {
            return 0;//出现次数为2次的数少于2,不能构成平行四边形
        } else {
            return max;
        }
    }
}
2.排序次数

有一种算法定义如下,该算法每次只能把一个元素提到序列的开头,例如2,1,3,4,只需要一次就可以把原序列从小到大有序。
现在给定乱序1-n的排列,请你计算最少需要多少次操作才能使得原序列从小到大有序。
输入:

2 1 3 4

输出:

1

思路:
比如:1 3 6 4 5 2
我们观察最大的数6不用移动,
a.6右边的数全部要移动,就是1+1+1=3次(移动的次序不一定,但是次数一定是3)
b.6左边的数,因为排序后和6挨着的一定是4 5,所以前面的两个数不是4 5这样的排序的话一定是移动1+1=2次
c.所以一共需要移动3+2=5次。

综上算法:
1.我们先需要找到最大数所在的序号
2.最大数右边数的个数为a
3.最大数左边的数需要按照自然数的顺序排到N------(N-3, N-2, N-1, N)-----违反规则的个数为b,例如(1 2 5 6 4 3),左边1和2不满足规则的,所以b为2
3.最后的排序的个数为a+b

------下面的代码是借助了一个排完序的数组brr:1 2 3 4 5 6
用i和j从右向左来遍历对比数组,思路是一样的,大家可以画图试一下,只不过麻烦了
直接用上面的思路暴力查找会简单些

import java.util.Arrays;
import java.util.Scanner;
/**
 * @author liu
 * @Description
 */
public class Main1 {
    public static void main(String[] args) {
    	//输入N
        Scanner ss1 = new Scanner(System.in);
        int N = ss1.nextInt();
		//连续输入n个数,并存入数组中
        Scanner ss2 = new Scanner(System.in);
        String[] str = ss2.nextLine().split(" ");
        int[] a = new int[str.length];
        for(int i = 0;i<str.length;i++){
            a[i] = Integer.parseInt(String.valueOf(str[i]));
        }

		//计算次数
        int pp = fun(N,a);
        System.out.println(pp);
    }
	//函数
    private static int fun(int n, int[] arr) {
    	//1.得到一个有序的数组brr
        int[] brr = arr.clone();   
        Arrays.sort(brr);
        
        int j = n-1; //记录brr的位置
        int sum = 0; //记录移动次数
        for(int i = n-1;i>=0; i--){
            if(arr[i] == brr[j]){
                j--;//相等时brr的j向前移动,for循环中i向前移动了,不用管
            }else{
                    sum++;//不等时,次数加1,for循环中i向前移动了,不用管
            }
        }
        return sum;
    }
}
3.杀怪游戏

在X轴上得x点位置,技能可以造成[x-y,x+y]范围内得怪物造成-1点得AOE伤害。问需要多少技能,可以杀死所有怪物
输入:

第一行:n y 怪物得数量和伤害得范围
接下来有n行
-每行:x hp 怪物的位置和怪物的血量

输出:

使用技能的次数

这一题参考牛客网大佬解答:
https://www.nowcoder.com/discuss/457660?type=post&order=time&pos=&page=1&channel=0&source_id=search_post

#include<bits/stdc++.h>
 
using namespace std;
 
struct node {    //定义怪物结点
    int x;
    int hp;
}a[100005];
 
bool cmp(node a, node b) {   //结点排序,自定义排序方式
    return a.x < b.x;
}
 
int main()
{
    int n,y;
    cin >> n >> y;
 
    for(int i = 0; i < n; i++) {
        cin >> a[i].x >> a[i].hp;
    }
 
    sort(a,a+n,cmp);   //对怪物进行排序,防止怪物位置乱序情况
 
    int res = 0, left = 0;
    while(left < n) {
        int kill = a[left].hp;
        res += kill;
 
        int j = left+1;
        while(a[j].x <= 2*y + a[left].x) {   //在区间的怪物,都相应的减少首个怪物扣除的血量kill
            a[j].hp -= kill;
            j++;
        }
 
        int k = left+1;     //往后遍历,找到还有血量的怪物
        while(a[k].hp <= 0) {    
            k++;
        }
 
        left = k;
    }
 
    cout << res << endl;
    return 0;
}

猜你喜欢

转载自blog.csdn.net/weixin_45773603/article/details/107524296