前提
使用言語 python
質問内容
pythonで競技プログラミングの勉強をしています.
AOJの二分探索の問題https://onlinejudge.u-aizu.ac.jp/courses/lesson/1/ALDS1/4/ALDS1_4_Bを以下のソースコードを使用して解いたのですが
python
1def i_input(): return int(input()) 2def i_map(): return map(int, input().split()) 3 4 5# listにitemがあったらTrue, なければFalseを返す 6def binary_search(list, item): 7 low = 0 8 high = len(list) - 1 9 while low <= high: 10 mid = (low + high) // 2 11 guess = list[mid] 12 if guess == item: 13 return True 14 elif guess > item: 15 high = mid - 1 16 else: 17 low = mid + 1 18 return False 19 20 21n = i_input() 22s = list(i_map()) 23q = i_input() 24t = list(i_map()) 25 26count = 0 27for i in t: # tの要素がsに含まれているか確認 28 if binary_search(s, i): 29 count += 1 30print(count)
めぐる式二分探索を使って解けずに困っています.(どのように判定式を記述すれば良いか分からない)
python
1def is_ok(mid): 2 """ 3 二分探索中の判定 4 :param mid: 5 """ 6 # ここの条件式をどう書けばよいかわかりません 7 pass 8 9 10def meguru_bisect(ng, ok): 11 12 while (abs(ok - ng) > 1): 13 mid = (ok + ng) // 2 14 if is_ok(mid): 15 ok = mid 16 else: 17 ng = mid 18 return ok 19
全体のソースコード(修正・追加箇所)
python
1# スニペット(再利用可能なソースコード) 2def i_input(): return int(input()) 3 4 5def i_map(): return map(int, input().split()) 6 7 8def is_ok(key): 9 # ここの部分の判定方法がわかりません. 10 11 if s[key] == i: 12 return True 13 else: 14 return False 15 16 17 18def binary_search(ng, ok): 19 while abs(ok - ng) > 1: 20 mid = (ok + ng) // 2 21 if is_ok(mid): 22 ok = mid 23 else: 24 ng = mid 25 return ng 26 27n = i_input() 28s = list(i_map()) 29q = i_input() 30t = i_map() 31 32count = 0 33for i in t: 34 # ngがリストの右端までいくとtの要素(i)を含んでいないと判定 35 if binary_search(-1, n) != n: 36 count += 1 37 38print(count)
実現したいこと
- めぐる式二分探索を使用してhttps://onlinejudge.u-aizu.ac.jp/courses/lesson/1/ALDS1/4/ALDS1_4_Bを解く.
最後に
初めての質問 & Markdown記法なので至らない点があると思いますがよろしくお願いします.
あなたの悩んでいる部分がまさに競技プログラミングの醍醐味なんじゃないでしょうか。どうやってアルゴリズムをコードに落として期待する結果を得るかを考えるのが醍醐味じゃないんですか?それを質問するとは一体どういうことでしょうか。
meguru_bisect をどのように呼び出して判定するかにより、is_ok の中身の書き方も変わってきます。
meguru_bisect を呼び出す部分のソースも追加してください。
slemntqeさん
返信ありがとうございます。
ご不快な思いをさせて申し訳ございません.
おっしゃる通り、分からない部分を悩んでそれを解決できた時の達成感。それが競技プログラミングの醍醐味の一つだと思います.
いつもは、質問せず"どうやったらこの問題を解けるのか"を考えて取り組んでおります。(2日以上考えたこともあります)
しかし、何日も考えても分からずに結果的に放置してしまうことが増えていました。
そこで、拙い質問の仕方ですが今回質問させていただきました。
ご容赦いただけますと幸いです。
atcorbugさん
返信ありがとうございます。
全体ソースコード
def i_input(): return int(input())
def i_map(): return map(int, input().split())
def is_ok(key):
# ここの部分の判定方法がわかりません.
if s[key] == i:
return True
else:
return False
def binary_search(ng, ok):
while abs(ok - ng) > 1:
mid = (ok + ng) // 2
if is_ok(mid):
ok = mid
else:
ng = mid
return ng
n = i_input()
s = list(i_map())
q = i_input()
t = i_map()
count = 0
for i in t:
# ngがリストの右端までいくとtの要素(i)を含んでいないと判定
if binary_search(-1, n) != n:
count += 1
print(count)
コードの追加方法など不備がございましたら、ご指摘お願い致しします
全体ソースコードは、ここに書くのではなく、質問を編集して書き替えてください。
あと、そもそも binary_search の結果の判定方法が間違っているので、is_ok をどのように書いても正しい結果になることはありません。
今回の問題における、めぐる式二分探索の戻り値は、「ソート順を維持する場合に挿入される位置」を表します。
例えば、sが「1, 2, 4, 5」の時、「3」を探すと「2」が返ります。
2番目(数字の4)の位置の直前に「3」を入れると、ソート順が維持されるためです。
つまり、探した数字が戻り値の位置に存在するとは限らないということになります。
めぐる式については、以下のページが詳しいので、読んでみてください。
二分探索アルゴリズムを一般化 〜 めぐる式二分探索法のススメ 〜
https://qiita.com/drken/items/97e37dd6143e33a64c8c
actorbugさん
返信ありがとうございます。
質問を編集し全体のソースコードを追加しました。
また、解説ありがとうございます。actorbugさんの解説の紹介してくださった記事をもとにめぐる式二分探索法について勉強し直してみます。
回答2件
あなたの回答
tips
プレビュー