処理速度が遅いために、みなさんにより処理速度の速い書き方を教わりたいと思い、相談いたします。
【やりたいこと】
・以下の数値を2個ずつ組み合わせることで、規定値(8)以上になるようにしたいと考えています。
**※なお、一度使った数値は、再使用することはできません。**この条件で、8以上となる組み合わせは最大何通りできるかを出力したいです。
[4 6 5 1 5 3]
上記数値の場合、
4 + 5 =9
6 + 3 =9
残っている数値:1と5 では、8以上とできないため、8以上となる組み合わせはこの場合、2通りとなります。
数値の組み合わせを変更して、
4 + 5 =9
5 + 3 =8
残っている数値:1と6 では、8以上とできないため、8以上となる組み合わせはこの場合も2通りとなります。
今回の数値では組み合わせをどう変更しても、2通りまでしかできないため、この場合、2通りを出力します。
上記を実現するため、私が書いた最初のコードです。
少ない数値なら問題なく動きましたが、今回扱う数値の数は、
・最大10万個
・数値の幅は、1 ~ 1,000,000,000
となるため、現在のコードでは、TLEとなっております。
python
1high = 8 2li = [4,6,5,1,5,3] 3li = sorted(li) 4cou = 0 5for i in range(len(li)): 6 for j in range(i+1,len(li)): 7 if li[i] + li[j] >= high: 8 cou +=1 9 li[i] =0 10 li[j] =0 11 12print(cou)
TLEを避けるため、改良したコードが下記です。
※速度は少し改善しましたが、TLEはいまだにおきています。
「やったこと」
・一番高い値を足しても、規定値以上ならない低い値は、その時点で削除しておく。
・昇順ソートしてから、リストの値をひとつずつ比較しているのは前回と同じで、今回、規定値以上となる値を見つけた場所をベースに、
それより上の値がいくつあるのかを出して、その分をパターンに追加しています。そうすることにより、forの流れる回数を減らしている。
python
1high = 8 2li = [4,6,5,1,5,3] 3li = [i for i in li if i + max(li) >= high] # 一番高い数値を足しても、規定値を満たさない値は、事前に削除 4li = sorted(li) 5cou = 0 6while li: 7 flag = 0 # 1回でもtrueなら、繰り返す 8 end="" 9 cont="" 10 for i in range(len(li)): 11 for j in range(i+1,len(li)): 12 if li[i] + li[j] >= high: 13 flag =1 14 cou +=1 15 ind_max = len(li[j+1:]) #後ろにいくつあるか 16 ind_min = len(li[i+1:j]) 17 if ind_min == ind_max: #同じ数 18 cou += ind_max 19 end ="END" 20 break #終了 21 elif ind_min < ind_max: #大きい値のがおおい 22 cou += ind_min 23 cou += (ind_max - ind_min) // 2 24 end ="END" 25 break #終了 26 27 elif ind_min > ind_max: #小さい値のがおおい 28 cou += ind_max 29 li = li[i+1+ind_max:j] #リストの値を更新 30 cont = "True" 31 break 32 if end == "END": #終了 33 li=[] 34 break 35 elif cont =="True": 36 break #リストを更新して最初から繰り返す 37 if flag == 0: #forを最後まで流して、一回もtrueじゃなければ、規定値以上はもう作れない 38 li=[] 39 break 40print(cou)
解決したいこと、聞きたいこと。
上記ように処理を最大100,000回ほど繰り返す必要があるのですが、
上記のコードがボトルネックになっていて、処理速度がとても遅いです。
Pythonを使う前提で、上記のゴールを達成するできるだけ速いコードの書き方を提案してもらえないでしょうか。
どうぞよろしくお願いします。
【追記】
ご解答頂いた内容でコード作成しました。
速度は少し改善できました。ありがとうございます。
しかし、TLEはおきてしまっています。
python
1high = 8 2li = [4,6,5,1,5,3] 3li = [i for i in li if i + max(li) >= high] # 一番高い数値を足しても、規定値を満たさない値は、事前に削除 4li = sorted(li) 5cou = 0 6 7while li: 8 obj = 0 9 value = high - li[-1] #value値以上の最小を見つける 10 for line,i in enumerate(li): 11 if i >= value and line+1 < len(li): #後半の条件は、末尾でないということ 12 obj = li[line] #見つかった。 13 break 14 if obj == 0: #見つからなかった。 15 break 16 else: 17 cou +=1 18 del li[-1] 19 del li[:line+1] 20print(cou)
【再追記】
ご教授いただいた点を考慮。
コード再作成。
python
1high = 8 2li = [4,6,5,1,5,3] 3li = [i for i in li if i + max(li) >= high] # 一番高い数値を足しても、規定値を満たさない値は、事前に削除 4li = sorted(li) 5cou = 0 6ind_max = len(li)-1 7ind_min = 0 8 9while li: 10 obj = 0 11 value = high - li[ind_max] #value値以上の最小を見つける 12 for i in range(ind_min,ind_max): 13 if li[i] >= value : #見つかった。 14 obj = li[i] 15 break 16 if obj == 0: #見つからなかった。 17 break 18 else: #見つかった 19 cou +=1 20 ind_max -=1 21 ind_min = i +1 #リストの値を削除するのではなく、移動 22 23print(cou) 24
【コード完成】
python
1n,high = map(int,input().split()) 2li = list(map(int,input().split())) 3max_li = max(li) 4li = [i for i in li if i + max_li >= high] # 一番高い雪を足しても、高さが満たさない雪だまは削除 5li = sorted(li) 6cou = 0 7ind_max = len(li)-1 # 5 8ind_min = 0 9 10while li: 11 obj = 0 12 value = high - li[ind_max] #value値以上の最小を見つける 13 for i in range(ind_min,ind_max): 14 if li[i] >= value : #見つかった。 15 obj = li[i] 16 break 17 if obj == 0: #見つからなかった。 18 break 19 else: #見つかった 20 cou +=1 21 ind_max -=1 22 ind_min = i +1 23 24print(cou)
回答2件
あなたの回答
tips
プレビュー
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
2018/09/19 09:51