牛客网刷题笔记(二)

4.迷路的牛牛

题目描述

牛牛去犇犇老师家补课,出门的时候面向北方,但是现在他迷路了。虽然他手里有一张地图,但是他需要知道自己面向哪个方向,请你帮帮他。

输入描述:

每个输入包含一个测试用例。
每个测试用例的第一行包含一个正整数,表示转方向的次数N(N<=1000)。
接下来的一行包含一个长度为N的字符串,由L和R组成,L表示向左转,R表示向右转。

输出描述:

输出牛牛最后面向的方向,N表示北,S表示南,E表示东,W表示西。

示例1

输入

3
LRR

输出

E

解题思路:

左转和右转会相互抵消,所以统计一下最后是向左转还是向右转,而且向一个方向转4次就到原来的方向了,所以对4取模之后在计算。

import java.util.Scanner;

public class Main {
    public static void main(String[] args) {
        Scanner in = new Scanner(System.in);
        int number = in.nextInt();
        if (number <= 0) {
            System.out.println("N");;
            return;
        }
        String turnString = in.next();
        char[] turnChar = turnString.toCharArray();
        int leftNum = 0, rightNum = 0;
        for (int i = 0; i < number; i++) {
            if (turnChar[i] == 'L') {
                leftNum++;
            }
            if (turnChar[i] == 'R') {
                rightNum++;
            }
        }
        //大于0表示最后是向左转,小于0表示最后是向右转
        int lastLeftNum = (leftNum - rightNum ) % 4;

        char[] director = new char[]{'N', 'W', 'S', 'E'};
        //全部转换为向左转
        System.out.println(director[(lastLeftNum + 4) % 4]);

    }
}

5.数对

题目描述

牛牛以前在老师那里得到了一个正整数数对(x, y), 牛牛忘记他们具体是多少了。

但是牛牛记得老师告诉过他x和y均不大于n, 并且x除以y的余数大于等于k。

牛牛希望你能帮他计算一共有多少个可能的数对。

输入描述:

输入包括两个正整数n,k(1 <= n <= 10^5, 0 <= k <= n - 1)。

输出描述:

对于每个测试用例, 输出一个正整数表示可能的数对数量。

示例1

输入

5 2

输出

7

说明

满足条件的数对有(2,3),(2,4),(2,5),(3,4),(3,5),(4,5),(5,3)

解题思路:

朴素的做法是枚举n^2个点然后跟k作比较。这显然对n<=100000的规模来说是不允许通过的。

注意到当除数是y时,当x=1~n时,余数是1,2,3,…,y-1,0循环出现,循环节长度显然是y

那么我们可以枚举y=k~n(当y

然后对于x=1~n,总共出现了[n/y]个循环节,然后数出每个循环节里面不小于k的余数。最后再数出不满一个循环节的不小于k的余数,就是答案了。注意当k=0的时候由于余数0出现在循环的末尾,因此要特别判断。

复杂度为O(n)

import java.util.Scanner;

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

        long count = 0;
        //按列统计,对于每一个y,当y>k时,这一列才会出现余数为k的情况,且是以1,2,...,y-1,0的循环形式出现的
        for (int y = k + 1; y <= n; y++) {
            count += (n / y) * (y - k);
            if ((n % y) >= k) {
                //k是否为0
                if (k != 0) {
                    count += ((n % y) - k + 1);
                } else {
                    count += n % y;
                }
            }
        }
        System.out.println(count);
    }
}

6.矩形重叠

题目描述

平面内有n个矩形, 第i个矩形的左下角坐标为(x1[i], y1[i]), 右上角坐标为(x2[i], y2[i])。

如果两个或者多个矩形有公共区域则认为它们是相互重叠的(不考虑边界和角落)。

请你计算出平面内重叠矩形数量最多的地方,有多少个矩形相互重叠。

输入描述:

输入包括五行。
第一行包括一个整数n(2 <= n <= 50), 表示矩形的个数。
第二行包括n个整数x1[i](-10^9 <= x1[i] <= 10^9),表示左下角的横坐标。
第三行包括n个整数y1[i](-10^9 <= y1[i] <= 10^9),表示左下角的纵坐标。
第四行包括n个整数x2[i](-10^9 <= x2[i] <= 10^9),表示右上角的横坐标。
第五行包括n个整数y2[i](-10^9 <= y2[i] <= 10^9),表示右上角的纵坐标。

输出描述:

输出一个正整数, 表示最多的地方有多少个矩形相互重叠,如果矩形都不互相重叠,输出1。

示例1

输入

2
0 90
0 90
100 200
100 200

输出

2

解题思路:

先试试暴力求解,遍历所有的单位矩形,找到最多的那个

import java.util.Scanner;

public class Main {
    public static void main(String[] args) {
        Scanner in = new Scanner(System.in);
        int n = in.nextInt();
        int x1Min = 0, y1Min = 0, x2Max = 0, y2Max = 0;
        int[][] coordinates = new int[4][n];
        for (int i = 0; i < 4; i++) {
            for (int j = 0; j < n; j++) {
                coordinates[i][j] = in.nextInt();
            }
        }

        //找出最左下角和最右上角的坐标
        for (int k = 0; k < n; k++) {
            if (coordinates[0][k] < x1Min) {
                x1Min = coordinates[0][k];
            }
            if (coordinates[1][k] < y1Min) {
                y1Min = coordinates[1][k];
            }
            if (coordinates[2][k] > x2Max) {
                x2Max = coordinates[2][k];
            }
            if (coordinates[3][k] > y2Max) {
                y2Max = coordinates[3][k];
            }
        }

        int maxCount = 0;
        for (int i = x1Min; i < x2Max; i++) {
            for (int j = y1Min; j < y2Max; j++) {
                int count = 0;
                //遍历所有的矩形
                for (int k = 0; k < n; k++) {
                    //如果该小方块包含在该矩形中,计数+1
                    if (i >= coordinates[0][k] && j >= coordinates[1][k]
                            && (i + 1) <= coordinates[2][k] && (j + 1) <= coordinates[3][k]) {
                        count++;
                    }
                }
                if (maxCount < count) {
                    maxCount = count;
                }
            }
        }
        System.out.println(maxCount);
    }
}

果然超时。。。过了50%,要做一下优化。理论上最多重叠矩阵的地方应该在矩形的边缘出现。因此,把循环遍历的条件改一下:

        for (int i : coordinates[0]) {
            for (int j : coordinates[1]) {
                int count = 0;
                //遍历所有的矩形
                for (int k = 0; k < n; k++) {
                    //如果该小方块包含在该矩形中,计数+1
                    if (i >= coordinates[0][k] && j >= coordinates[1][k]
                            && (i + 1) <= coordinates[2][k] && (j + 1) <= coordinates[3][k]) {
                        count++;
                    }
                }
                if (maxCount < count) {
                    maxCount = count;
                }
            }
        }

通过了

你可能感兴趣的:(刷题笔记)