算法训练#13:思维题之Almost Rectangle和Array_and_Peaks

20 阅读1分钟

“开启掘金成长之旅!这是我参与「掘金日新计划 · 2 月更文挑战」的第 16 天,点击查看活动详情

第一题

Almost Rectangle

题目理解

给出一个矩阵,里面只有“ . ”和“ * ”两种值,其中“ * ”只有两个,且一定处在同一行或者同一列,需要在矩阵中把“ * ”的位置分布变成正方形(也就是从两个增加到四个)再把变化后的矩阵输出

输入

第一行输入整数tt表示案例的个数、,其中1t1021\le t\le10^{2}
案例的第一行输入整数nn、,其中2n4002\le n\le400
案例的第二行到第n+1n+1行,每行输入nn个字符,其中都是“ . ”和“ * ”

输出

输出一个矩阵——对应变化后的矩阵

思路

很明显,这道题可以用一个最暴力的方法——分类讨论:记录下两个“ * ”的位置,分类讨论两个“ * ”所处的位置,若在同一列,则把相邻的一行的对应位置的“ . ”变成“ * ”,若在同一行,则把相邻的一列的对应位置的“ . ”变成“ * ”,然后再把矩阵输出即可

代码

import java.util.Scanner;

public class Almost_Rectangle {
    public static void main(String args[]) {
        Scanner sc = new Scanner(System.in);
        int t = sc.nextInt();
        for (int i = 0; i < t; i++) {
            int n=sc.nextInt();
            char[][] x=new char[n][n];
            for(int j=0;j<n;j++) {
                String a=sc.next();
                for (int k = 0; k < n; k++) {
                    x[j][k]=a.charAt(k);
                }
            }
            int[][] xy=new int[4][2];
            int count=0;
            for(int j=0;j<n;j++) {
                for (int k = 0; k < n; k++) {
                    if(x[j][k]=='*') {
                        xy[count][0] = j;
                        xy[count][1] = k;
                        count++;
                    }
                }
            }
            if(xy[0][0]==xy[1][0])
            {
            //边界判断
                if(xy[0][0]==0)
                {
                    xy[2][0]=xy[0][0]+1;
                    xy[2][1]=xy[0][1];
                    xy[3][0]=xy[1][0]+1;
                    xy[3][1]=xy[1][1];
                }
                else
                {
                    xy[2][0]=xy[0][0]-1;
                    xy[2][1]=xy[0][1];
                    xy[3][0]=xy[1][0]-1;
                    xy[3][1]=xy[1][1];
                }
            }
            else if(xy[0][1]==xy[1][1])
            {
            //同上
                if(xy[0][1]==0)
                {
                    xy[2][0]=xy[0][0];
                    xy[2][1]=xy[0][1]+1;
                    xy[3][0]=xy[1][0];
                    xy[3][1]=xy[1][1]+1;
                }
                else
                {
                    xy[2][0]=xy[0][0];
                    xy[2][1]=xy[0][1]-1;
                    xy[3][0]=xy[1][0];
                    xy[3][1]=xy[1][1]-1;
                }
            }
            else
            {
                xy[2][0]=xy[0][0];
                xy[2][1]=xy[1][1];
                xy[3][0]=xy[1][0];
                xy[3][1]=xy[0][1];
            }
            x[xy[2][0]][xy[2][1]]='*';
            x[xy[3][0]][xy[3][1]]='*';
            for(int j=0;j<n;j++) {
                for (int k = 0; k < n; k++) {
                    System.out.print(x[j][k]);
                }
                System.out.println();
            }
        }
    }
}

第二题

Array and Peaks

image.png

题目理解

给出两个整数nnkk,要求输出一个长度为nn、取值为11nn、且有kk个“峰”的数组
“峰”的意思是数组中的一个元素要大于它旁边的两个元素,那么就可以说有一个“峰”

输入

第一行输入整数tt表示案例的个数、,其中1t1001\le t\le100
案例的第一行输入整数nn、,其中1n1001\le n\le1000kn0\le k\le n\

输出

输出答案数组,若不能生成答案数组,则输出-1

思路

单纯的去生成一个有足够“峰”的随机数组是比较困难的,所以我们要去寻求用固定的方式去生成符合答案要求的数组。有一个方法:如果我们把数组按升序排列,然后从最后往前遍历,需要“峰”的时候,我们就把该元素和其前面的元素对调,这样就肯定可以形成“峰”了,需要多少个“峰”,我们就再往前进行多少次这样的操作即可。不过要注意:这样做的时候当次交换的位置与上次交换的位置不能有重合的地方(假设上次交换的下标是4、5,那这次交换的下标就得是2,3,而不能是3、4,这样会导致只有一个“峰”)。根据此思路,对能否产生足够峰我们也可以用很简单的方式去判断:只要2k+1n2k+1\le n,该数组就可以生成足够多的“峰”

代码

import java.util.Scanner;

public class Array_and_Peaks {
    public static void main(String args[]) {
        Scanner sc = new Scanner(System.in);
        int t = sc.nextInt();
        for (int i = 0; i < t; i++) {
            int n=sc.nextInt();
            int k=sc.nextInt();
            //能否生成的判定
            if(n==1&&k==0)
                System.out.println(1);
            else if((float)n/2<=k)
                System.out.println(-1);
            else {
                int[] x=new int[n];
                for(int j=0;j<n;j++) {
                    x[j]=j+1;
                }
                int end=n-1;
                //生成足够的“峰”
                while(k>0) {
                    int temp=x[end];
                    x[end]=x[end-1];
                    x[end-1]=temp;
                    end-=2;
                    k--;
                }
                for(int j=0;j<n;j++) {
                    System.out.print(x[j]+" ");
                }
            }
        }
    }
}