这是题目
,很容易就看出接的雨水的形状是倒三角类型的,我觉得和for循环打印三角形差不多;
只是这个图像有三角形和烟囱形的形式,反正最上面雨水那一层总是比下面那一层的多。
浅浅画一个
以下是这道题的代码,虽然做出来了但是没提交leetcode,因为不知道咋写那种输入
import java.lang.*;
import java.util.Scanner;
/**
* 0 0 1 0 2 1 0 1 3 2 1 2 1 0
* 在n个柱子旁边加上地平线“0”,那么数组为a[n-1]和a[n+1]就为0
* 用a[i] < a[i + n] && a[i] < a[i - 1]找到最小值,(n = 1、2、3...) ,然后count+1
* 找到a[i-1]与a[i+n]之间的数,随着n的增大,里面的值就越多,我用for循环去count++;
* 然后定义一个变量add(称为count之前的值),如果count一直在增加,那么就不扩大n,即区间的范围。
* 当count==add,那么就增大区间,即n++
*
* 关键代码:
* for (int n = 1;n<=size-2;){
* int add = count;
* for(int i = 1;i < size-1;i++){
* if (i + n <size -1) {
* if (a[i] < a[i + n] && a[i] < a[i - 1]) {
* for (int j = 0; j < n; j++) {
* a[i + j]++;
* count++;
* }
* }
* }
* }if( count == add){n++;}
* }
*
* ---------------------------------------------------------------------------
* size是你加了地平线的数组长度,size = n+2
*/
public class asd {
public static void main(String[] args) {
int count = 0; //计算能接多少雨水
Scanner s = new Scanner(System.in);
System.out.println("输入你的数组长度为:");//size-2 = n
final int size = s.nextInt();
if (size <= 4){
System.out.println("一共接了"+count+"滴水");
System.exit(0);
}
int a[] = new int[size];
a[0] = 0;
for (int i = 1;i<size-1;i++){
int x = s.nextInt();
a[i] = x;
}
a[size-1] = 0;
//打印现在的数组情况
System.out.println("开始的数组情况为:");
for (int i = 0;i<size;i++){
System.out.print(a[i]+"\t");
}
//开始解题
for (int n = 1;n<=size-2;){
int add = count;
for(int i = 1;i < size-1;i++){
if (i + n <size -1) {
if (a[i] < a[i + n] && a[i] < a[i - 1]) {
for (int j = 0; j < n; j++) {
a[i + j]++;
count++;
}
}
}
}if( count == add){n++;}
}
//打印接水后的数组情况
System.out.println();
System.out.println("结束的数组情况为:");
for (int i = 0;i<size;i++){
System.out.print(a[i]+"\t");
}
System.out.println();
System.out.println("一共接了"+count+"滴水");
}
}
【没错,我猜你也想到了吧】
这种不规则形状的水咋办?先找底部的起点?然后走迷宫走出来?
那这样的呢?请问阁下该如何应对?稍微动动脑筋,
刚刚的 height = [0,1,0,2,1,0,1,3,2,1,2,1] 就当只是个一维的。 而我出的这个是二维的,可以表示成这样[
[0,0,0,0,0,0,1,0,0,0,0,0],
[0,0,0,0,1,0,1,1,1,0,0,0],
[0,0,0,0,1,0,1,1,1,1,0,1],
[1,1,1,0,1,0,1,0,0,0,0,1],
[1,0,0,0,1,0,1,1,0,0,0,1],
[1,1,0,0,1,0,0,0,1,0,1,1]]
那这就只不过是多了几行一维数组而已,只需再加个for循环而已,一行一行的判断,把1之间的0都变成1,再count就行了。
最开始那道接雨水的题也可以用这种方法做,只需要把一维变成二维,再把二维变成一维就行了
下面是代码
package com.newton.test;
import java.lang.*;
import java.util.Scanner;
/**
* 默认雨水的高度小于9,(可以自行更改的)
* 关键代码:
* for (int n = 1;n<=size-2;){
* int add = count;
* for (int j = 0;j<9;j++) {
* for (int i = 1; i < size - 1; i++) {
* if (i + n < size - 1) {
* if (a_copy[i][j] < a_copy[i + n][j] && a_copy[i][j] < a_copy[i - 1][j]) {
* for (int m = 0; m < n; m++) {
* a_copy[i + m][j]++;
* count++;
* }
* }
* }
* }
* }if( count == add){n++;}
* }
*/
public class RainyDay_1_5 {
public static void main(String[] args) {
int count = 0; //计算能接多少雨水
Scanner s = new Scanner(System.in);
System.out.println("输入你的数组长度为:");//size-2 = n
final int size = s.nextInt();
int a_copy[][] = new int[size][9]; //9代表的是雨水的高度的最大值
if (size <= 4){
System.out.println("一共接了"+count+"滴水");
System.exit(0);
}
int b[] = new int[size];
int a[] = new int[size];
a[0] = 0;
for (int i = 1;i<size-1;i++){
int x = s.nextInt();
a[i] = x;
}
a[size-1] = 0;
//打印现在的一维数组情况
System.out.println("开始的数组情况为:");
for (int i = 0;i<size;i++){
System.out.print(a[i]+"\t");
}
System.out.println();
System.out.println("将一维数组变为二维...");
for (int i = 0;i<size;i++){
for (int j=0;j<a[i];j++){
a_copy[i][j] = 1;
}
}
//打印现在的二维数组情况
System.out.println("现在的二维数组情况为:");
for (int j = 0;j<9;j++){
for (int i = 0;i<size;i++){
System.out.print(a_copy[i][j]+"\t");
}
System.out.println();
}
//开始解题
for (int n = 1;n<=size-2;){
int add = count;
for (int j = 0;j<9;j++) {
for (int i = 1; i < size - 1; i++) {
if (i + n < size - 1) {
if (a_copy[i][j] < a_copy[i + n][j] && a_copy[i][j] < a_copy[i - 1][j]) {
for (int m = 0; m < n; m++) {
a_copy[i + m][j]++;
count++;
}
}
}
}
}if( count == add){n++;}
}
//打印现在的二维数组情况
System.out.println("现在的二维数组情况为:");
for (int j = 0;j<9;j++){
for (int i = 0;i<size;i++){
System.out.print(a_copy[i][j]+"\t");
}
System.out.println();
}
System.out.println("将二维降为一维");
//将二维数组降为一维
int count_2;
for (int j = 0;j<9;j++){
for (int i = 0;i<size;i++){
if (a_copy[i][j] == 1){
b[i]++;
}
}
}
//打印接水后的数组情况
System.out.println();
System.out.println("结束的数组情况为:");
for (int i = 0;i<size;i++){
System.out.print(b[i]+"\t");
}
System.out.println();
System.out.println("一共接了"+count+"滴水");
}
}
运行一下,
好了,接下来是三维的接雨水了,题目是这样的
这样的
大家别被吓到了哦,草履虫都知道被子能装多少水得从杯口俯视着看,你看杯子侧面那只是凭经验猜测能装多少水。
那么,这一道题也还是二维的。刚刚第一题是从左往右判断a[i] < a[i + n] && a[i] < a[i - 1]。
这一题就得增加一个从上往下判断了。
解释在代码里面也有,自己看吧
import java.lang.*;
import java.util.Scanner;
/**
* heightMap = [[1,4,3,1,3,2],[3,2,1,3,2,4],[2,3,3,2,3,1]]
* length = 8 ;width = 5
* 1 4 3 1 3 2 1 4 3 "3" 3 2 | 1 4 3 "3" 3 2
* 3 2 1 3 2 4 ---length--->7di 3 "3" "3" 3 "3" 4 | ---width-->0di 3 "3" "3" 3 "3" 4
* 2 3 3 2 3 1 2 3 3 "3" 3 1 | 2 3 3 "3" 3 1
* ——————————————————————————————————————————————————————————
* 1 4 3 1 3 2 1 4 3 1 3 2 | 1 4 3 "3" 3 2
* 3 2 1 3 2 4 ----width-->4di 3 "3" "3" 3 "3" 4 |---length-->3di 3 "3" "3" 3 "3" 4
* 2 3 3 2 3 1 2 3 3 2 3 1 | 2 3 3 "3" 3 1
* ——————————————————————————————————————————————————————————
* 我们分别看 length的 和width的
* 很容易就看出,length和width重叠的那一部分才是真正该count++的地方
* 1 4 3 1 3 2 1 4 3 1 3 2
* 即为 3 2 1 3 2 4 ------>4di 3 "3" "3" 3 "3" 4
* 2 3 3 2 3 1 2 3 3 2 3 1
*
* 例子1:length = 7 ,width = 7
* 3 3 3 3 3
* 3 2 2 2 3
* 3 2 1 2 3
* 3 2 2 2 3
* 3 3 3 3 3
* 例子2:length = 13, width = 13
* 9 9 9 9 9 9 9 9 9 9 9
* 9 8 8 8 8 8 8 8 8 8 9
* 9 8 7 7 7 7 7 7 7 8 9
* 9 8 7 6 6 6 6 6 7 8 9
* 9 8 7 6 5 5 5 6 7 8 9
* 9 8 7 6 5 0 5 6 7 8 9
* 9 8 7 6 5 5 5 6 7 8 9
* 9 8 7 6 5 5 5 6 7 8 9
* 9 8 7 7 7 7 7 7 7 8 9
* 9 8 8 8 8 8 8 8 8 8 9
* 9 9 9 9 9 9 9 9 9 9 9
*
*/
public class RainyDay_2 {
public static void main(String[] args) {
double count = 0; //计算能接多少雨水
Scanner s = new Scanner(System.in);
System.out.println("输入你的数组长度为:");//length-2 = n
final int length = s.nextInt();
System.out.println("输入你的数组宽度为:");//width-2 = n
final int width = s.nextInt();
double a_copy[][] = new double[length][width];
double moment[][] = new double[length][width]; // 全为0的暂时数组
for (int j = 0;j<width;j++){
for (int i = 0;i<length;i++){
moment[i][j] = 0;
}
}
if (length <= 4 && width <=4){
System.out.println("一共接了"+count+"滴水");
System.exit(0);
}
//补齐二维数组左侧的“0” ,其实数组自带补“0”
double a[][] = new double[length][width];
for (int j = 1;j<width-1;j++){
a[0][j] = 0;
}
//输入二维数组
for (int j = 1;j<width-1;j++){
for (int i = 1;i<length-1;i++){
int x = s.nextInt();
a[i][j] = x;
}
}
//补齐二维数组右侧的“0”,其实数组自带补“0”
for (int j = 1;j<width-1;j++){
a[length-1][j] = 0;
}
//打印现在的数组情况
System.out.println("开始的数组情况为:");
for (int j = 1;j<width-1;j++){
for (int i = 1;i<length-1;i++){
a_copy[i][j] = a[i][j];
System.out.print((int)a[i][j]+"\t");
}
System.out.println();
}
//开始解题
for (int n = 1;n<=length-2;){
count = (int)count;
double add = count;
for (int j = 1;j<width-1;j++) { //从第一排到第二排依次检测,横向的length i
for (int i = 1; i < length - 1; i++) {
if (i + n < length) {
if (a[i][j] < a[i + n][j] && a[i][j] < a[i - 1][j]) {
for (int m = 0; m < n; m++) {
a[i + m][j] ++;
moment[i+m][j] ++; //一个临时的moment[i][j]数组,可以暂时存放增加的痕迹
count = count + 0.001; //count不能加一,但是需要微小变化
}
}
}
}
}if (count == add) {
n++;
}
}
for (int n = 1;n<=width-2;){
double add = count;
for (int j = 1;j<width-1; j++) { //从第一列到第二列依次检测 纵向的width j
for (int i = 1; i < length - 1; i++) {
if (j + n < width) { //用新的a_copy来增加,如有之前增加的痕迹再增加count
if (a_copy[i][j] < a_copy[i][j + n] && a_copy[i][j] < a_copy[i][j - 1] && (moment[i][j] > 0)) {
for (int m = 0; m < n; m++) {
a_copy[i][j + m] = a_copy[i][j + m] + 1;
count = count + 1;
}
}
}
}
}if (count == add) {
n++;
}
}
//打印接水后的数组情况
System.out.println();
System.out.println("结束的数组情况为:");
for (int j = 1;j<width-1;j++){
for (int i = 1;i<length-1;i++){
System.out.print((int)a_copy[i][j]+"\t");
}
System.out.println();
}
System.out.println();
System.out.println("一共接了"+(int)count+"滴水");
}
}
运行一下,怕你们不信
至于推广到多维度的,比如说四维的东西能接多少雨水.....也许只是多一个for循环,感兴趣的话可以尝试去思考思考,顺便思考一下四维的杯子长啥样吧哈哈哈