[プログラマー]中秋節の流量2ℋ


コードテスト練習-[第1ラウンド]中秋流量

再オープン


まず、私はこれらの問題を無条件に整数型に変換して解決するのが好きです.
問題では、秒単位で最大小数点の3番目のビットに設定されているので、doubleタイプに変換するとx 1000になります.
各タスクの開始時間からリクエスト完了時間までmilisec単位に変換するタイムライン配列を生成します.
この質問は回答完了時間を基準に昇順に並べられています.
  • 可能な限り多くの要求を含める場合、「ある要求の応答完了時間から」1 secは区間である.このようにしてこそ、その時間終了のお願いが含まれますから.
  • このセグメントに含まれるリクエストは、「セグメントの終了時間」>=「リクエストの開始時間」のリクエストである.
  • class Solution {
        int[][] timeLines;
        public int solution(String[] lines) {
            int answer = 0;
            int lLen = lines.length; // task의 개수 
            // timeLines : 시작시간 , 완료시간 
            timeLines = new int[lLen][2];
            convertLines(lines);
            // 구하기 : 모든 완료시간을 iterate하면서, 해당시간 + 1000 - 1 이, 어떤 작업의 시작시간 이상이면 count를 한다  
            int max = 0,cnt = 0; 
            int criteria = 0; // 기준이 되는 완료시간 
            for(int i =0 ; i<lLen;i++){
                criteria = timeLines[i][1]+1000-1; 
                cnt = 1; 
                for(int j=i+1;j<lLen;j++){
                    if(timeLines[j][0]<=criteria)cnt++;
                }
                max = Math.max(max,cnt);
            }
            answer = max;
            
            return answer;
        }
        
        
        public void convertLines(String[] lines){
            String line = null;
            int t = 0; // 요청완료시간 정보를 milisec 로 변환한 정보 
            for(int i =0;i<lines.length;i++){
                line = lines[i];
                String[] times = line.split(" ");   // times[2] 는 처리하는데에 걸린 시간
                String[] compT = times[1].split(":"); // 요청 완료 시간 관련 정보
                // compT[0] 은 hh , compT[1]은 mm , compT[2]는 ss.sss 
                t = Integer.parseInt(compT[0])*3600;
                t += Integer.parseInt(compT[1])*60;
                t *= 1000;
                t += (int)(Double.parseDouble(compT[2])*1000);
                timeLines[i][1] = t; // 요청완료 시간 기록 
                timeLines[i][0] = t - ((int)(Double.parseDouble(times[2].split("s")[0])*1000) )+ 1; // 요청 시작 시간 
                // System.out.println(timeLines[i][0]+"~"+timeLines[i][1]);
            }
        }
        
    }

    初めて解いた時。

  • 秒の最大スループットは、[完了するかどうかはxによって決定される]応答の任意の時間から1秒の処理を開始する要求の最大数を意味する.
  • 固定長2016-09-15 hh:mm:ss.sss処理時間T
  • 処理時間Tは、小数点の3番目に多く記録され、後に秒単位を示すsが続く.
  • Tは0.001以上3.000以下である.
  • 入力線は、応答完了時間Sを基準として昇順に並べられている.
  • つまり、
  • 「完了」は必要ありません.
  • 終了時からスライドウィンドウを使用してもいいですか?
  • スライドウィンドウを行っても0.001 s単位で移動しますが、時間の複雑さは大丈夫でしょうか?
  • を使用してウィンドウをスライドする場合、この問題の範囲は非常に広いです.逆にそうすると、タイムアウトの危険がさらに大きくなります.
  • [時間][分][秒][ミリ秒]

  • まず正規表現を使うことを学ばなければならない.

  • スペースを中心に「2016-09-15」、「hh:mm:ss.sss」、「ts」を分割

  • 破棄日.

  • 「hh:mm:ss.sss」を「:」中心に分割します.

  • TSはsubstringを使用してsを除去し、このStringをdoubleに変換する.この時は少し注意が必要です.
    Java ParseDoubleの使用を無効にするときに注意するポイント-ダブルインデックス
  • 50分ほど悩んだあげく、他人の解答を見た。

  • 問題の簡略化は重要
  • 題は「終了時間」を「昇順」として情報を与えた.
  • 私の考え
  • msも見ているので、あるログの時間情報の境界線ではないところからの1秒が正解かもしれないと思います.でもendを基準にすると大した問題じゃない…!
  • まず時間単位を調整します。


  • 「1秒」が大事で、double型を使うと混乱すると思いますが、それはもっと快適です.s単位で格納する.

  • sに変換し、->x 1000をms単位で保存します.24 X 60 x 60 x 1000=86400000なのでintタイプで格納できます.

  • 時間はhh:mm:ssです.sssなので、

  • hh x 3600 + mm x 60 + ss.sssを格納します.(「:」を基準として分割)

  • ss.sssのようなStringは直接Doubleに変換し、->1000で乗算する方法を選択します.
    💥この時DoubleParseDouble(String s)を使用すると指数形式で現れるので、それを避けるためにNumberFormatを使用した.
    Java ParseDoubleの使用を無効にするときに注意するポイント-ダブルインデックス

  • 各ログに開始時間と終了時間の配列を作成します.
  • 簡単に考えてみたい。


  • フルナビゲーションを使用します.総ログは2000個程度しかないので、全体的な探索を行うのも良い問題です.N^2でも400万個くらいあるから大丈夫

  • 重要なのは,問題において,[終了時間]を基準として,[昇順]の情報と+[完了していなくても]のカウントを与えることである.


  • for文を使用してendarrayを呼び出します.
  • の最初のendを基準にstart array for文を使用して回転します.
  • end[i]時間を基準として、1秒はi+1からn種類のログの「start時間」より大きくなければならない.
  • public static void set(int[] start, int[] end,String[] lines){
            for(int i=0;i<lines.length;i++){
                int endTime=0;
                int startTime=0;
                String[] seg = lines[i].split(" ");
                // Drop seg[0] --> seg[1] : hh:mm:ss.sss --> seg[2] : ?s
                String[] times = seg[1].split(":");
    
                int hour = Integer.parseInt(times[0]);
                int min = Integer.parseInt(times[1]);
                int secmsec = (int)(Double.parseDouble(times[2]) *1000);
                endTime += 3600 *hour;
                endTime += 60*min;
                endTime*=1000;
                endTime += secmsec;
                // seg[2]
                int lapse = (int)(Double.parseDouble(seg[2].substring(0,seg[2].length()-1)) *1000);
                startTime = endTime-lapse+1;
                start[i]=startTime;
                end[i] =endTime;
            }
        }
        public static int solution(String[] lines) {
            int answer = 0;
            NumberFormat format = NumberFormat.getInstance();
            format.setGroupingUsed(false);
            int[] start = new int[lines.length];
            int[] end = new int[lines.length];
            set(start,end,lines);
            int max = Integer.MIN_VALUE;
            int curCnt=0;
            for(int i=0;i<lines.length;i++){
                curCnt=0;
                int curCond = end[i]+1000-1;
                for(int j=i;j<lines.length;j++){
                    if(curCond>=start[j]) curCnt++;
                }
                if(max<curCnt)max =curCnt;
            }
            answer = max;
            return answer;
        }
    
        public static void main(String[] args) {
            int res = solution(new String[]{
                            "2016-09-15 20:59:57.421 0.351s",
                    "2016-09-15 20:59:58.233 1.181s",
                    "2016-09-15 20:59:58.299 0.8s",
                    "2016-09-15 20:59:58.688 1.041s",
                    "2016-09-15 20:59:59.591 1.412s",
                    "2016-09-15 21:00:00.464 1.466s",
                    "2016-09-15 21:00:00.741 1.581s",
                    "2016-09-15 21:00:00.748 2.31s",
                    "2016-09-15 21:00:00.966 0.381s",
                    "2016-09-15 21:00:02.066 2.62s"
            });
            System.out.println(res);
    
        }

    20210923再オープン


    (28分)
  • 秒あたりの最大スループット
  • 要求の[応答するか否かX]は、タスクが1000秒以内である場合、スループットは
  • である.
  • から1000 msecまでの最大リクエスト数
  • :linesアレイに対して、毎秒最大スループットを返す必要があります.
  • 指定された
  • のString[]行は2000ログ文字列を超えない
  • 応答完了時間S処理時間Tが出現した.
  • 回答完了時間Sを基準として昇順に並びます.
  • S形式:2016-09-15 hh:mm:ss.sssフォーマット
  • T形式:小数点の3番目のビット(可能)+後にsで終了
  • 0.1s
  • 0.312s
  • 2s
  • 処理時間は、開始時間、終了時間を含む.→0.010秒から、処理時間が0.011 sなら→0.010+0.0.11-0.001.
  • 処理時間は0.001以上3.000以下である.
  • 草の考え


    第一の考え:単位を転換する


    与えられたログデータフォーマットは2016-09-15 hh:mm:ssである.sssなので、s単位またはmsec単位に変換する必要がある場合があります.私はfloatフォーマットに詳しくないので、整数形式に変換します.
  • msec単位:24 x 60 x 1000ㅍ=8640万→intタイプ格納可能
  • まず糸をつないで割る
    String[] temp = lines[i].split(" ");
    // temp[1]은 hh:mm:ss.sss 를 temp[2]는 T를 담고 있다. 
    String[] times = temp[1].split(":"); 
    // 
  • Integer.ParseInt("01")->1に変換できます.
  • 💥 問題を感じる部分はTが与える形式が2 s=2.0 sであり,2.00 sであってもよい.
  • 2.0s
  • 2s
  • 1.562s
  • は、これを二重タイプに変換し、1000を乗じてintタイプに変換する.
  • 一部の条件:ログの完了時間から開始

  • どうせ「あるログの完了時間」を起点にしなければならない.
    -あるログの完了時間を起点とする1 secセグメントについて、次のログの実行時間が含まれているかどうかを確認できます-->つまり、完全な探索を考えました.
  • 完全探索?
  • 2000個のログをそれぞれ1 secの起点として、ログの後ろのログが1 sec区間→2000 x 2000に含まれているかどうかをチェックし、400万程度かもしれません.
  • また、この問題の状況は昇順で、200091998号...1番はこのような回数で行います
  • 最終コード

    class Solution {
        
        public int max = 0; 
        public void solve(int[] fin, int[] task){
            int cnt =0;
            // 전체 탐색
            for(int i=0;i<fin.length;i++){
                cnt =0; 
                // fin[i]+1000 - 1(i 번째 task의 완료시간을 포함하여 1sec 동안)  이 fin[j]-task[j]+1 (j번째 task의 수행시간동안 겹치는 시간이있는지를 )이상인지를 체크한다. 
                for(int j=i;j<fin.length;j++){
                    if(fin[i]+1000-1>=fin[j]-task[j]+1) cnt++;
                }
                if(max<cnt) max = cnt; 
            }
        }
        public int solution(String[] lines){
            int answer =0;
            int[] fin = new int[lines.length]; // 완료시간을 msec 단위로 저장
            int[] task = new int[lines.length]; // 완료하는데 걸리는 시간을 msec단위로 저장
            // 처리
            String[] temp = null;
            String[] times = null;
            int cnt=0,i=0;
            for(String line:lines){
                cnt =0;
                temp = line.split(" ");
                times = temp[1].split(":");
                cnt+=Integer.parseInt(times[0])*60*60; // 01
                cnt+=Integer.parseInt(times[1])*60; // 00
                cnt*=1000;
                cnt += (int) (Double.parseDouble(times[2]) * 1000);
                fin[i]=cnt;
                task[i++] = (int) (Double.parseDouble(temp[2].split("s")[0]) * 1000);
            }
            solve(fin,task);
            answer = max;
            return answer;
    
        }
    }
    정확성  테스트
    테스트 1 〉	통과 (0.76ms, 69.4MB)
    테스트 2 〉	통과 (11.23ms, 86.3MB)
    테스트 3 〉	통과 (11.93ms, 71.2MB)
    테스트 4 〉	통과 (115.80ms, 92MB)
    테스트 5 〉	통과 (2.46ms, 77.8MB)
    테스트 6 〉	통과 (2.24ms, 69.4MB)
    테스트 7 〉	통과 (18.98ms, 86.5MB)
    테스트 8 〉	통과 (12.46ms, 75MB)
    테스트 9 〉	통과 (2.71ms, 73.2MB)
    테스트 10 〉	통과 (0.53ms, 75.9MB)
    테스트 11 〉	통과 (0.57ms, 75.9MB)
    테스트 12 〉	통과 (17.76ms, 82.6MB)
    테스트 13 〉	통과 (2.32ms, 71.3MB)
    테스트 14 〉	통과 (0.45ms, 75.5MB)
    테스트 15 〉	통과 (0.45ms, 66.5MB)
    테스트 16 〉	통과 (0.74ms, 70.4MB)
    테스트 17 〉	통과 (2.70ms, 79.9MB)
    테스트 18 〉	통과 (21.23ms, 80.6MB)
    테스트 19 〉	통과 (23.43ms, 101MB)
    테스트 20 〉	통과 (15.85ms, 94.4MB)
    테스트 21 〉	통과 (0.39ms, 73.4MB)
    테스트 22 〉	통과 (0.40ms, 72.9MB)
  • は、文字列の変換方法を以前よりも少なく考慮しています.
  • を解く悩みは少なくなったようだ.