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

歡迎訪問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 编程语言 > java >内容正文

java

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

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

寫(xiě)在前面

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

題目要求

P1567題目鏈接

簡(jiǎn)單分析

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

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

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

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

第一次提交——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

這個(gè)寫(xiě)的太沙雕了,無(wú)法形容……我還有臉?lè)懦鰜?lái)~~

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

這次多跑了一會(huì)兒,看來(lái)是“優(yōu)化”了一點(diǎn)兒~~

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

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

每一次加一個(gè)GC玩玩,超時(shí)了……

確實(shí),GC耗時(shí)啊……

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

每一萬(wàn)次GC一次,結(jié)果部分通過(guò),部分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

干脆開(kāi)到50000次一個(gè)GC,結(jié)果不夠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

后來(lái)發(fā)現(xiàn)打錯(cuò)了,輸了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后復(fù)盤,將此處改為每30000次循環(huán)GC一次:

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

再測(cè)試,30000和70000處分別GC一次:

再測(cè)試,30000和60000分別GC一次:

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

第八次提交——MLE

這是當(dāng)時(shí)測(cè)的,現(xiàn)在看來(lái)就沒(méi)啥意義了~~MLE唄

只不過(guò)將close提前了,可惜沒(méi)用,該爆還得爆~~

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

這個(gè)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(); :

還是不行哇!!

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

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

GC不是辦法,因?yàn)镚C會(huì)帶來(lái)大量的性能損耗(主要是時(shí)間,導(dǎo)致了TLE;要是時(shí)間不爆表,空間肯定回收不夠……)

之前有的算法雖然不見(jiàn)得那么好,但我用C能過(guò),Java不能過(guò),顯然問(wèn)題在Java身上。

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

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

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

最終提交——柳暗花明又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);} }

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

但還是給自己點(diǎn)掌聲!!!So——

總結(jié)

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

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