こんにちは、こんぶちゃ(茶コーダー)です!
初心者視点から競プロAtCoderのABC329のA問題〜C問題の自身の解答と解答説明をしていきます。
まだまだ学習の身ですので、最適コードではない部分も多々あるかと思いますが、その部分は同じ学習者として温かい気持ちで応援&ご助言頂けば嬉しいです。
では早速行ってみましょう!
今回の参加コンテスト(ABC329)
A問題:Spread
問題文
英大文字からなる文字列 S が与えられます。S の各文字を空白で区切り、その順で 1 文字ずつ出力してください。
解答
# 文字列の各文字を空白で区切り、1文字ずつ出力
print(" ".join(input()))
解き方)
input()
を使ってユーザーから文字列を入力します。join
メソッドを使って、文字列を空白で区切りながら結合します。- 結合した文字列を
print
関数で出力します。
B問題:Next
問題(要約)
N 個の整数 A1,A2,…,AN が与えられます。 このうち最大でない整数の中で最大である整数を求めてください。ただし、この問題の制約下で答えは必ず存在します。
解答
n=input()
# 空白で区切られた整数を取得
# 重複を排除して昇順にソートし、最大でない整数の中で最大の値を取得して出力
print(sorted(list(set(map(int,input().split()))), reverse=True)[1])
解き方)
input()
を使ってユーザーから整数の個数 N を入力します(この部分では実際には使われていません)。input()
を使って空白で区切られた整数を取得し、map
を使って各要素を整数に変換します。set
を使って重複を排除し、sorted
を使って昇順にソートします。reverse=True
を指定することで逆順(降順)になり、その中でインデックスが 1 の値(最大でない整数の最大値)を取得します。- 結果を出力します。
C問題:Count xxx
C – Count xxx
問題(要約)
英小文字からなる文字列 S が与えられる。S の異なる1文字からなる部分文字列の数を求めよ。ただし、同じ文字の部分文字列は同じものとして扱う。
解答
from itertools import groupby
# 入力: 文字列の長さ n と文字列 S
n = int(input())
S = input()
# 文字の出現回数をタプルのリストに格納
substr_counts = [(sub, len(list(i))) for sub, i in groupby(S)]
# 出現回数で降順ソート
sorted_substr_counts = sorted(substr_counts, key=lambda x: x[1], reverse=True)
# 出現回数の最も多い異なる1文字からなる部分文字列を求める
words = set()
ans = 0
for sub, count in sorted_substr_counts:
if sub not in words:
ans += count
words.add(sub)
# 結果を出力
print(ans)
解き方)
- 入力された文字列
S
から連続する同じ文字の部分文字列をグループ化し、それぞれの文字とその出現回数のタプルを取得。 - 出現回数で降順にソート。
- ソートされた結果を元に、最も出現回数が多い異なる1文字からなる部分文字列を抽出。
- 出現回数を合計して、異なる1文字からなる部分文字列の総数を求めて出力。
感想
今週もC問題まで解けました!C問題で苦戦しましたが、回答に辿り着けました ^^
A、B問題はすぐに回答に辿り着けました。問題は比較的簡単でしたので、ここではコードをまとめて記載してみました。なんちゃって上級者気分です。ここだけの話ですが、コンテスト時は愚直にfor文回して解いています。
C問題は、初めは単語に対してfor文を回して、文字をリストに登録し、数を数えました。残念ながら実行制限時間超過。リストから集合に変えたりと試行錯誤を繰り返し、3回目の再実装で上記の答えに辿り着きました。
実装の正確性は上がってきましたが、実行時間を考えたアルゴリズム実装の練習が必要なので、精進して行きます。
Ratingは若干下がってしまいましたが、自身の最高点に近い551点なので、来週も頑張りたいと思います。
それでは、良い競プロライフを~!(*^▽^)/
コメント