プログラマー:ベストアルバム、3進反転、最小矩形、2016年(曜日)、シーザーパスワード、すべて0


ベストアルバム


1. Problem

2. My Solution
  • genes dict:key=タイプ、value=総再生数
  • genes song:key=タイプ、value=[(i 1曲目、再生数),.]
  • genes rank:genes dict総再生数降順ソート
  • 再生数に基づいて音楽タイプを降順にソート->高い音楽タイプから、そのタイプの曲と再生数を含むリストをソートし、1つまたは2つのpop()
  • を選択します.
    def solution(genres, plays):
        
        answer = []
        genres_dict = dict()
        genres_song  = dict()
        genres_rank = []
        
        
        for i in range(len(genres)):
            genres_dict[genres[i]] = genres_dict.get(genres[i],0) + plays[i]
            genres_song[genres[i]] = genres_song.get(genres[i],[]) + [(i,plays[i])]
        
        # print(genres_dict) = {'classic': 1450, 'pop': 3100}
        # print(genres_song) = {'classic': [(0, 500), (2, 150), (3, 800)], 'pop': [(1, 600), (4, 2500)]}
        	
        for i in genres_dict.items():
            genres_rank.append(i)
            
        genres_rank.sort(key = lambda x:x[1], reverse = True)
        
        # print(genres_rank) = [('pop', 3100), ('classic', 1450)]
        
        for i in range(len(genres_dict)):
            
             # 재생횟수를 기준으로 1차정렬(오름차순), 인덱스를 기준으로 2차정렬(내림차순)
            genres_song[genres_rank[i][0]].sort(key = lambda x:(x[1], -x[0]))  
            
            for _ in range(min(2,len(genres_song[genres_rank[i][0]]))):
                answer.append(genres_song[genres_rank[i][0]].pop()[0])
            
        return answer
    3. Learned
  • sort(キー=lambda x:x[0])の降順ソート:指定-x[0]
  • フリップバイナリ


    1. Problem

    2. My Solution
    def change(n):
        result = []
        
        while(n > 0):
            n,mod = divmod(n,3) 
            result.append(mod)
         
        return "".join(map(str,result))
    
    def solution(n):
        return int(change(n),3)
    3. Learned
  • 意外にも大量の変換進数の機能が必要である.Googlingであれば変換部分を導入するだけで良いのですが、googlingができない場合は直接実現しなければならないので、ある程度公式のように暗記します
  • 10進->2,8,16進変換bin()、oct()およびhex()関数
  • を使用
  • n進->10進からint(num,n進)関数
  • に変換

    最小長方形


    1. Problem

    2. My Solution
  • 財布の横または縦の長さを指定する必要があります.これは名刺の最大長です.
  • 最大長さを決定した場合は、名刺に小さな長さ(上で指定した長さと一致する長さ)を指定し、財布の残りの部分
  • に最大長さを指定します.
    def solution(sizes):
        w = sorted(sizes, key = lambda x:x[0])
        h = sorted(sizes, key = lambda x:x[1])
        max_value = max(w[-1][0], h[-1][1])
        second_value = 1
        
        for i in sizes:
            if second_value < min(i):
                second_value = min(i)
        
        return max_value * second_value
    
    3. Others' Solution
    def solution(sizes):
        return max(max(x) for x in sizes) * max(min(x) for x in sizes)
    4. Learned
  • コード再構成によりコードサイズを縮小し、可読性を向上
  • // 길이가 가장 큰 부분을 구하는 코드 
    w = sorted(sizes, key = lambda x:x[0])
    h = sorted(sizes, key = lambda x:x[1])
    max_value = max(w[-1][0], h[-1][1])
    
    => max(max(x) for x in sizes)
    
    
    // 명함에서 길이가 작은 것들 중에서 가장 큰 부분을 구하는 코드
    for i in sizes:
        if second_value < min(i):
            second_value = min(i)
            
    => max(min(x) for x in sizes)

    2016年(取得曜日)


    1. Problem

    2. My Solution
  • datetimeモジュールのweekday()関数は、この日付の週の整数値
  • を取得します.
  • 0:月曜日から6:日曜日
  • import datetime
    
    def solution(a, b):
        weekday_match = ["MON","TUE","WED","THU","FRI","SAT","SUN"]
        return weekday_match[datetime.datetime(2016,a,b).weekday()]
    3. Learned
  • 日付の計算が必要な問題が頻繁に発生するため、日付に関連するモジュールdatetime(コメントサイト)
  • の使用方法を理解する必要があります.

    シーザーのパスワード


    1. Problem

    2. My Solution
    def solution(s, n):
        answer = ""
    
        for alphabet in s:
    
            asci = ord(alphabet)+n
    
            if alphabet.isspace():
                answer += " "
            elif alphabet.islower():
                if asci > 122:
                    answer += chr(96+asci-122)
                else:
                    answer += chr(asci)
            else:
                if asci > 90:
                    answer += chr(64+asci-90)
                else:
                    answer += chr(asci)
    
        return answer
    3. Others' Solution
    def solution(s, n):
        answer = ""
        
        for alphabet in s:
            
            if alphabet.isspace():
                answer += " "
            elif alphabet.islower():
                answer += chr(((ord(alphabet)-97+n)%26)+97)
            else:
                answer += chr(((ord(alphabet)-65+n)%26)+65)
                
        return answer
    4. Learned
  • 循環アルファベットの問題が頻繁に発生し、順方向または逆方向の循環
  • // n 번 만큼 정방향으로 이동한다고 할 때
    // -1%26 = 25 이므로 -n 번 만큼 역방향으로 이동한다고 할 때도 동일하게 사용
    chr(((ord(alphabet)-65+n)%26)+65)

    すべて0に変更


    1. Problem

    2. My Solution
  • 重み付け合計が0の場合、-1
  • を出力する必要があります.
  • 動作を最小限に抑えるためには、接続する幹線の数を小さいノードから0にしなければならないと考えられるため、ノードに接続する幹線の数をそれぞれ計算する必要がある.幹線の数を昇順に並べ、ノードの順に0を生成してからマイナス->失敗(行動するノードを特定すると、無順序でランダムに並べ替えられ、途中で中断することもあります)
  • def solution(a, edges):
        
        graph = [[] for _ in range(len(a))]
        conn_cnt = [0] * len(a)
        order = []
        answer = 0
        
        # 가중치의 총합이 0이 아니면 만들 수 없으므로 return -1
        if sum(a) != 0:
            return -1
        
        # 연결된 간선의 수를 기준으로 오름차순 정렬하는 부분 
        for edge in edges:
            conn_cnt[edge[0]] += 1
            conn_cnt[edge[1]] += 1
            graph[edge[0]].append(edge[1])
            graph[edge[1]].append(edge[0])
        
        for idx,cnt in enumerate(conn_cnt):
            order.append((idx,cnt))
        
        order.sort(key = lambda x:x[1])
        
        # 간선의 수가 작은 노드부터 0으로 만듬
        for node, _ in order:
            for victim in graph[node]:
                if a[victim] != 0:
                    a[victim] += a[node]
                    answer += abs(a[node])
                    a[node] = 0
                    
        return answer
    3. Others' Solution
  • グラフィックは常にツリー形式で表示されるので、任意のノードをルートノード、リーフノードからルートノード、0
  • に設定できます.
  • dfsは、dfsの呼び出し時にルートノードからリーフノードにアクセスすることを可能にし、dfsの呼び出しが終了して戻ったときにリーフノードからルートノードに移動する
  • import sys
    sys.setrecursionlimit(10**8)
    
    def solution(a, edges):
        
        def dfs(node):
            
            nonlocal answer
            visited[node] = True
            
            for u in graph[node]:
                if visited[u] == False and a[u] != 0:
                    dfs(u)
                    a[node] += a[u]
                    answer += abs(a[u])
                    
                    
        graph = [[] for _ in range(len(a))]
        visited = [False] * len(a)
        answer = 0
        
        # 가중치의 총합이 0이 아니면 만들 수 없으므로 return -1
        if sum(a) != 0:
            return -1
        
        for u,v in edges:
            graph[u].append(v)
            graph[v].append(u)
        
        dfs(0)
            
        return answer
    4. Learned
  • ツリーでDFSアルゴリズムを使用してルートノードからリーフノードにアクセスします.逆に考えればリーフノードからルートノードへのアクセス原理も考えられる