日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程语言 > java >内容正文

java

高时空损耗的Scanner会卡爆程序(记洛谷P1567的Java性能优化,Java语言描述)

發(fā)布時間:2025/3/15 java 42 豆豆
生活随笔 收集整理的這篇文章主要介紹了 高时空损耗的Scanner会卡爆程序(记洛谷P1567的Java性能优化,Java语言描述) 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

寫在前面

對性能調(diào)優(yōu),其實我一個弱雞,用的也不多,特別是這種OJ連JVM調(diào)優(yōu)都不成。
大佬s勿噴,且看小菜雞如何在一道OJ題里與Java性能搏斗!

題目要求

P1567題目鏈接

簡單分析

10^9,沒超int,但是數(shù)值里也必須用int。

10^6,這么大數(shù)組,想坑死我嗎?真狼啊。

這題開始沒注意,后來發(fā)現(xiàn)卡性能,這么難的情況下還卡那么狠——1s+125MB,這個對C/C++還行,對Java真的不友好,極為不友好!!!

程設思路簡潔——逐一比較并由counter記錄即可,counter記錄完與max比較。注意的是學會將i在遍歷的時候進行跳躍是對性能的極大優(yōu)化(雖然本題里這么做沒啥用~~)

第一次提交——MLE

猝不及防的MLE,人傻了都!!

import java.util.Scanner;public class Main {public static void main(String[] args) {Scanner scanner = new Scanner(System.in);int num = scanner.nextInt();int[] array = new int[num];for (int i = 0; i < num; i++) {array[i] = scanner.nextInt();}int max = 0;for (int i = 0; i < num; ) {int counter = 1;int j;for (j = i+1; j < num; j++) {if (array[j-1] < array[j]) {counter++;} else {break;}}i = j;if (max < counter) {max = counter;}}System.out.println(max);scanner.close();} }

第二次提交——MLE+WA

這個寫的太沙雕了,無法形容……我還有臉放出來~~

import java.util.Scanner;public class Main {public static void main(String[] args) {Scanner scanner = new Scanner(System.in);int num = scanner.nextInt();int first = scanner.nextInt();int counter = 1;int max = 0;for (int i = 1; i < num; i++) {int temp = scanner.nextInt();if (first < temp) {counter++;first = temp;} else {if (max < counter) {max = counter;}counter = 1;}}System.out.println(max);scanner.close();} }

第三次提交——MLE

這次多跑了一會兒,看來是“優(yōu)化”了一點兒~~

在算法上改了改,可惜不行……

import java.util.Scanner;public class Main {public static void main(String[] args) {Scanner scanner = new Scanner(System.in);int tem1 = 0, tem2 = 0, counter = 0, max = 0;int num = scanner.nextInt();for(int k = 0; k < num; k++) {tem2 = scanner.nextInt();if (tem2 > tem1)counter++;else{max = (counter > max) ? counter : max;counter = 0;}tem1 = tem2;}System.out.println(max+1);scanner.close();} }

第四次提交——TLE

每一次加一個GC玩玩,超時了……

確實,GC耗時啊……

import java.util.Scanner;public class Main {public static void main(String[] args) {Scanner scanner = new Scanner(System.in);int tem1 = 0, tem2 = 0, counter = 0, max = 0;int num = scanner.nextInt();for(int k = 0; k < num; k++) {tem2 = scanner.nextInt();if (tem2 > tem1) {counter++;} else {max = Math.max(counter, max);counter = 0;}tem1 = tem2;System.gc();}System.out.println(max+1);scanner.close();} }

第五次提交——TLE

每一萬次GC一次,結果部分通過,部分TLE。

顯然10000次/GC一次,還是頻率太高了:

import java.util.Scanner;public class Main {public static void main(String[] args) {Scanner scanner = new Scanner(System.in);int tem1 = 0, tem2 = 0, counter = 0, max = 0;int num = scanner.nextInt();for(int k = 0; k < num; k++) {tem2 = scanner.nextInt();if (tem2 > tem1) {counter++;} else {max = Math.max(counter, max);counter = 0;}tem1 = tem2;if (k % 10000 == 0) {System.gc();}}System.out.println(max+1);scanner.close();} }

第六次提交——MLE

干脆開到50000次一個GC,結果不夠GC就爆掉內(nèi)存了,MLE:

import java.util.Scanner;public class Main {public static void main(String[] args) {Scanner scanner = new Scanner(System.in);int tem1 = 0, tem2 = 0, counter = 0, max = 0;int num = scanner.nextInt();for(int k = 0; k < num; k++) {tem2 = scanner.nextInt();if (tem2 > tem1) {counter++;} else {max = Math.max(counter, max);counter = 0;}tem1 = tem2;if (k == 50000) {System.gc();}}System.out.println(max+1);scanner.close();} }

第七次提交——TLE

后來發(fā)現(xiàn)打錯了,輸了3000,太沙雕了:

import java.util.Scanner;public class Main {public static void main(String[] args) {Scanner scanner = new Scanner(System.in);int tem1 = 0, tem2 = 0, counter = 0, max = 0;int num = scanner.nextInt();for(int k = 0; k < num; k++) {tem2 = scanner.nextInt();if (tem2 > tem1) {counter++;} else {max = Math.max(counter, max);counter = 0;}tem1 = tem2;if (k % 3000 == 0) {System.gc();}}System.out.println(max+1);scanner.close();} }


AC后復盤,將此處改為每30000次循環(huán)GC一次:

AC后復盤,將此處改為只在30000處GC一下:

再測試,30000和70000處分別GC一次:

再測試,30000和60000分別GC一次:

(這是事后測的,多次調(diào)參數(shù)都不行,特別是時空雙爆炸,基本證明這條路走不通~~)

第八次提交——MLE

這是當時測的,現(xiàn)在看來就沒啥意義了~~MLE唄

只不過將close提前了,可惜沒用,該爆還得爆~~

import java.util.Scanner;public class Main {public static void main(String[] args) {Scanner scanner = new Scanner(System.in);int num = scanner.nextInt();int[] array = new int[num];for (int i = 0; i < num; i++) {array[i] = scanner.nextInt();}scanner.close();int tem1 = array[0], tem2 = 0, counter = 0, max = 0;for(int i = 1; i < num; i++) {tem2 = array[i];if (tem2 > tem1) {counter++;} else {max = Math.max(counter, max);counter = 0;}tem1 = tem2;}System.out.println(max+1);} }

第九次提交——RE→MLE

這個RE是我智障,忘了加一行nextLine():

import java.util.Scanner;public class Main {public static void main(String[] args) {Scanner scanner = new Scanner(System.in);int num = scanner.nextInt();scanner.nextLine();int[] array = new int[num];String str = scanner.nextLine();scanner.close();String[] strings = str.split(" ");for (int i = 0; i < num; i++) {array[i] = Integer.parseInt(strings[i]);}System.gc();int tem1 = array[0], tem2 = 0, counter = 0, max = 0;for(int i = 1; i < num; i++) {tem2 = array[i];if (tem2 > tem1) {counter++;} else {max = Math.max(counter, max);counter = 0;}tem1 = tem2;}System.out.println(max+1);} }

在第七行插入: scanner.nextLine(); :

還是不行哇!!

……無數(shù)次失敗,看來性能瓶頸真的來了,可我不甘心……

但是我逐漸冷靜下來,思考著之前的種種策略。

GC不是辦法,因為GC會帶來大量的性能損耗(主要是時間,導致了TLE;要是時間不爆表,空間肯定回收不夠……)

之前有的算法雖然不見得那么好,但我用C能過,Java不能過,顯然問題在Java身上。

Java做這個題確實折磨一些,但我們正應該借此琢磨琢磨孰優(yōu)孰劣呢。

開辟的數(shù)組雖然大,但也不至于爆掉125MB內(nèi)存,而且C都能活下來,可見問題不在這里,就算你開大數(shù)組也未必直接爆炸,這可只有10W啊,也不至于100W啥的,那些太大的可能malloc不來……

我懷疑問題在Scanner身上,查了查性能調(diào)優(yōu)的資料,覺得這東西很煩人,應該是我性能的最大瓶頸~~就拿他開刀!!!

最終提交——柳暗花明又AC

import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader;public class Main {public static void main(String[] args) throws IOException {BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));int num = reader.read();reader.readLine();String[] arr = reader.readLine().split(" ");int counter = 0;int max = 0;for (int i = 1; i < arr.length; i++) {int tem1 = Integer.parseInt(arr[i]);int tem2 = Integer.parseInt(arr[i-1]);if((tem1 - tem2) > 0) {counter++;} else {max=Math.max(max, counter);counter = 0;}}System.out.println(max+1);} }

弱者落淚~~
敗者食塵~~

但還是給自己點掌聲!!!So——

總結

以上是生活随笔為你收集整理的高时空损耗的Scanner会卡爆程序(记洛谷P1567的Java性能优化,Java语言描述)的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。