#Runtime: 60 ms, faster than 83.47% of Python3 online submissions for Two Sum.
#Memory Usage: 15.3 MB, less than 42.38% of Python3 online submissions for Two Sum.
class Solution:
# Brute Force - 가장 단순한 접근 -> time complexity : (n2), space complexity : o(1)
def twoSum(self, nums,target):
target_indices = []
for i in range(0,len(nums)):
for j in range(i+1,len(nums)):
if nums[i] + nums[j] == target:
target_indices+=[i,j]
return target_indices
return target_indices
# Two - pass Hash Table -> time complexity : (n), space complexity : o(n)
def twoSum(self, nums,target):
hash_map = {}
target_indices = []
# 자료구조를 해시 맵으로 생성
for idx,va in enumerate(nums):
hash_map[va]=idx
# look up
for idx,va in enumerate(nums):
minus_value = target - va
if minus_value in hash_map and hash_map[minus_value] != idx:
target_indices+=[idx,hash_map[minus_value]]
break
return target_indices
# One pass hash Table -> time complexity : (n), space complexity : o(n)
def twoSum(self, nums,target):
hash_map={}
for idx,va in enumerate(nums):
minus_value = target-va
if minus_value in hash_map:
return [idx,hash_map[minus_value]]
hash_map[va]=idx
def test(self):
nums = [2,1,94,3,-2]
target = 92
result = self.twoSum(nums,target)
print(result)
if __name__ == '__main__':
s = Solution()
s.test()
3.코멘트
난 첫 번째 Brute Force 라고 부르는 방식으로 문제를 풀었다. (심플한 방법을 제일 좋아하기도 하고, 저 방법이 가장 먼저 떠올랐다. )
leetcode는 문제 제출에 대한 피드백이 비교적 잘 되있다. (시각화나, 해설, discussion도 있고..)
첫 번째 방식보다, 해시 기반의 자료구조를 이용했을때 시간복잡도가 매우 낮았다.
해시 맵을 만드는 방법도 생각을 안 한건 아니었지만, 해시 맵을 만든다고 하더라도, nums 배열의 full scan 비용 * 해시 맵 안에서 key 를 scan 비용을 더 하면 O(N2) 이 될거라고 생각했는데 아니었다. (해시 맵안에서는 키를 순회하는게 아니라 맵에 키가 있는지만 보면 되니까.. -_-; )
# -*- encoding: utf-8 -*-
#import sys
#input = sys.stdin.readline
def set_test_case():
commands = []
switch_size= int(input())
switch = input().split(' ')
switch = [int(x) for x in switch]
command_num = int(input())
for i in range(0,command_num):
command = input().split(' ')
#command = map(lambda x: int(x),command)
commands+=[[int(x) for x in command]]
return switch,commands
def switch_process(switch,gender,switch_pos):
switch=switch
switch_interval = switch_pos
if switch_pos == 0 :
return switch
# 남자의 경우 입력처리
if gender == 1:
while(switch_pos > 0 and switch_pos <= len(switch)):
switch[switch_pos-1] = switch[switch_pos-1] ^ 1 # XOR 연산, index -1 처리
switch_pos+=switch_interval # 배수 처리
# 여자의 경우 입력처리
elif gender == 2:
symmetry = True #대칭 여부의 flag 변수
l =switch_pos -2 # 대칭점 기준 왼쪽 포인터
r = switch_pos # 대칭점 기준 오른쪽 포인터
switch[switch_pos-1] = switch[switch_pos-1] ^ 1 # 대칭 여부와 상관없이, 대칭점의 스위치는 전환
while(symmetry and l >= 0 and r < len(switch)): # 대칭되는 스위치를 찾는 범위가 리스트의 범위를 벗어나지 않는 조건
if switch[l] == switch[r]:
switch[l] = switch[l] ^ 1
switch[r] = switch[r] ^ 1
l -= 1
r += 1
else:
# 대칭되지 않는 조건
symmetry=False
# 입력 케이스 예외처리 부분
else:
#exception
pass
return switch
def solution(switch,commnads):
for command in commnads:
gender,pos = command[0],command[1]
switch = switch_process(switch,gender,pos)
# 최대 출력 스위치 조건을 만족하기 위한 처리
num_by_line = 20
for i in range(0,len(switch),num_by_line):
print(*switch[i:i+num_by_line],sep=' ')
def main():
switch,commands = set_test_case()
solution(switch,commands)
if __name__ == '__main__':
main()
Spark SQL, DataFrame, streaming , MLlib 그리고 Spark Core 를 지원한다.
2. 왜 PySPark?
java, scala 로 작성된 코드가 성능이 조금 더 뛰어나다고 알려져 있다.
하지만 빅데이터 진영에서는 파이썬이 친숙한 사람이 많고, 생산성이 더 난다고 생각한다.
3. Pyspark 기초 - Dataframe 생성 및 다루기
** 개발할 때 비교적 자주 사용되는 함수만 다룰 것 이다.
- 조건 조회와 출력, 그리고 withColumn 은 정말 많이 사용되는 것 같다.
from pyspark.sql.types import *
from pyspark.sql.functions import col,lit
# 멤버 컬럼
member_columns = ['group_cd','join_dt','name','login_cnt']
# 멤버 데이터
member_data = [
('k-00001','2021-07-31','name1',10),
('k-00002','2021-06-31','name2',10),
('k-00003','2021-08-31','name3',10),
('k-00004','2021-03-31','name4',12),
('k-00001','2021-04-31','name5',11),
('k-00002','2021-05-31','name6',15),
]
# 데이터 프레임 생성
member_df = spark.createDataFrame(data=member_data,schema=member_columns)
#스키마 구조 출력
member_df.printSchema()
# withColumn - 새 컬럼 추가. literal 로 초기화해줘야 한다.
member_df= member_df.withColumn("use_flag",lit(False))
member_df.printSchema()
#pyspark 에서 countDistinct 사용을 위해서는 lib 를 선언 해줘야 하다니..
from pyspark.sql.functions import countDistinct
from pyspark.sql import functions as F
# 행 출력
member_df.show(10,truncate = False)
# 특정 컬럼 출력
member_df.select('join_dt','name','group_cd').show(10)
# groupby 출력
member_df.groupBy("group_cd").count().sort("count",ascending=True).show()
# filter 조건 출력
member_df.filter(member_df.login_cnt > 10).show()
# filter 조건을 복수 개로 줘보자
member_df.filter(
(F.col("group_cd") == "k-00001") &
(F.col("login_cnt") > 10)
).count()
# where 조건 출력
member_df.where(my_df.acntid=='name1').show()
member_df.filter("name == 'name1'").show()
non-dev 버전으로 띄웠더니 app, worker, db, cache (redis) 프로세스가 분리되어있다.
# yaml 소스 클론
$ git clone https://github.com/apache/superset.git
# 릴리즈 버전으로 체크아웃
$ git checkout 1.2.0
$ git status
# 컨테이너로 올리는 명령 실행
$ docker-compose -f docker-compose-non-dev.yml up -d
b) 브라우저 접속
초기 비밀번호는 admin/admin
http://localhost:8088 접속 (서버에 설치하신 분들은 localhost에 설치한 서버의 host 로 대체)
기본적으로 예제 데이터가 추가되어있는데, yaml 을 찾아보면 off 할 수 있다.
c) 데이터소스 추가 ( mysql)
상단 Data → Databases 클릭 → 우측상단에 + database 클릭 → DB 호스트 정보 기입 후 추가
동시성등을 고려한 개발을 프로그래머가 직접 해줄 필요가 없다 - 옵션 에서 동시성이나 병렬 제어가 가능하기 때문에
모니터링이 편하다.
데이터 엔지니어 입장에서 aws lambda 를 통한 스트리밍 처리도 가능하다고 생각한다. (허용되는 데이터 발생량이나 규모에 따라)
3. lambda 만들기
람다는 웹 콘솔에서 GUI 로도 손쉽게 만들 수 있다.
하지만 이번 포스팅은 로컬 서버에서 aws cli 를 이용하여 lambda 함수를 만들어 본다.
실습 예제는 aws 공식 홈페이지에 나와있는 내용들이다. ( 공식 홈페이지 가이드가 더 내용이 풍부하니까 그 쪽을 먼저 보길 바란다)
a) 사전 준비 (시간이 부족해서 생략)
로컬 PC 에서 aws cli 가 설치 및 IAM 구성이 되어 있어야 한다.
lambda 생성과 실행 등 필요한 IAM 권한이 미리 준비되어 있어야 한다 .
실행권한 arn 이 필요하다.
b) lambda 생성
# 워킹 디렉토리 생성 및 이동
$ mkdir lambda_python_sample
$ cd lambda_python_sample
# 람다 코드 작성
$ vi lambda_function.py
# 사용되는 패키지를 working 디렉토리에 다운로드
$ pip install --target ./package requests
$ cd package
# 패키지 압축
$ zip -r ../jssvs-development-package.zip .
# lambda 코드 압축
$ zip -g jssvs-deployment-package.zip lambda_function.py
# lambda 생성 명령어 - 함수이름, 압축 파일 경로, 이벤트 핸들러 명(function 이름) # 역할 arn 순으로.
$ aws lambda create-function --function-name lambda-jssvs-dev \
--zip-file fileb://[home dir]/WorkSpace/aws/lambda_python_sample/jssvs-deployment-package.zip \
--handler lambda_function.main --runtime python3.7 \
--role arn:aws:iam::[ars code]:role/gamebi-lambda-role
undo 명령구간에 모든 명령어는 취소하고, 남은 type 명령의 문자를 저장해서 출력하는 문제다.
undo 명령도 undo 에 의해 취소 될 수 있다.
2.코드
#입력 테스트 케이스 처리
def setTestCase():
N=input()
COMMAND_LIST = []
for i in range(int(N)):
COMMAND_LIST.append(input())
return COMMAND_LIST
#커맨드 라인 파싱
def command_parser(input_command_list):
command_list = []
for i in input_command_list:
split_command = i.split(" ")
command_type,command_content,seconds = split_command[0],split_command[1],int(split_command[2])
command_list.append((seconds,command_content))
return command_list
# 입력 처리
def process_command(command_list):
text = '' # 결과 문자열을 담을 변수
rollback_point=-1 # undo 의 분기를 찾을 카운트
# 명령어는 역순으로 처리
for command_set in reversed(list(command_list)):
seconds,command = command_set
# undo 가 적용되는 마지막 명령어 분기
if seconds == rollback_point:
rollback_point = -1
continue
# undo 가 해당되는 구간의 명령어 skip 분기
elif rollback_point != -1 and seconds > rollback_point:
continue
# undo 명령어를 만났을 때 분기
elif command.isdigit():
rollback_point = seconds - int(command)
if rollback_point < 0:
rollback_point = 0
continue
# 문자 저장
text+=command
return text[::-1] # 역순으로 결과 문자열이 저장되었기 때문에 reverse 처리
def solution():
input_command_list = setTestCase()
command_list=command_parser(input_command_list)
result = process_command(command_list)
print(result)
if __name__=='__main__':
solution()
3.코멘트
스택구조의 프로그램 호출 처리 흐름을 모방하여, 명령어를 역순으로 undo 범위에 해당되는 명령은 취소하여 문제를 해결했다.
생각한 테스트 케이스는 문제가 없었는데 실제 제출시 실패가 있었다.
함께 스터디한 스터디원에게 반례 케이스 정보를 얻어 문제를 해결할 수 있었다.
type/undo 가 0초일때 , 그리고 같은 초에 여러 명령어의 입력이 들어올 경우를 추가하여 테스트 했다.
언제나 그랬지만 함께 열심히 공부한 스터디원에게서 지식을 얻는다. .. (스터디원들에게 고맙다 )