<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
    <channel>
        <title>jup.log</title>
        <link>https://velog.io/</link>
        <description>:0</description>
        <lastBuildDate>Tue, 19 Nov 2024 06:45:30 GMT</lastBuildDate>
        <docs>https://validator.w3.org/feed/docs/rss2.html</docs>
        <generator>https://github.com/jpmonette/feed</generator>
        <image>
            <title>jup.log</title>
            <url>https://images.velog.io/images/jup-hui/profile/e527a909-0d35-4dcf-95ec-9dd1fb8c9530/KakaoTalk_20220314_140742309.png</url>
            <link>https://velog.io/</link>
        </image>
        <copyright>Copyright (C) 2019. jup.log. All rights reserved.</copyright>
        <atom:link href="https://v2.velog.io/rss/jup-hui" rel="self" type="application/rss+xml"/>
        <item>
            <title><![CDATA[DeepLearning Optimizer 비교 (Adam v.s. Adadelta)]]></title>
            <link>https://velog.io/@jup-hui/DeepLearning-Optimizer-%EB%B9%84%EA%B5%90-Adam-v.s.-Adadelta</link>
            <guid>https://velog.io/@jup-hui/DeepLearning-Optimizer-%EB%B9%84%EA%B5%90-Adam-v.s.-Adadelta</guid>
            <pubDate>Tue, 19 Nov 2024 06:45:30 GMT</pubDate>
            <description><![CDATA[<p>deeplearning optimizer 중 adadelta와 adam을 비교해보고자 한다.</p>
<p>아래 글과 코드는 &quot;실전! 파이토치 딥러닝&quot; 책을 참고하였다.</p>
<h1 id="1-adadelta--adam-수식">1. Adadelta &amp; Adam 수식</h1>
<p>두 알고리즘 모두 <strong>적응적 학습률(adaptive learning rate)</strong>을 사용
-&gt; 매개 변수의 변화률이 많을 수록 이후에는 낮은 속도의 학습률을 가짐</p>
<h2 id="11-adadelta">1.1 Adadelta</h2>
<ol>
<li>학습율 람다에 대한 정의가 필요 없음</li>
<li>이전 경사의 제곱 값을 활용함</li>
</ol>
<h2 id="12-adam">1.2 Adam</h2>
<ol>
<li>이전 경사의 제곱 값 뿐만 아니라 감소 크기도 활용함</li>
</ol>
<p>-&gt; 벡터의 방향과 크기 모두 고려.
2. 대체로 Adam 사용</p>
<h2 id="13-요약">1.3 요약</h2>
<p><img src="https://velog.velcdn.com/images/jup-hui/post/3e444045-85f1-4ca3-92e1-eef604c36e82/image.png" alt=""></p>
<h1 id="2-비교-실험">2. 비교 실험</h1>
<p>MNIST 학습 및 평가 실험을 통해서 두 Optimizer의 차이를 확인하자</p>
<p>epoch = 5
batch size = 32
learning rate for adam = 0.001</p>
<h1 id="21-모델-훈련-시간-궤적수렴">2.1. 모델 훈련 시간, 궤적(수렴)</h1>
<ul>
<li>one epoch 학습 시 소요된 시간 (1875개의 데이터 셋)</li>
</ul>
<ol>
<li>adadelta: 약 49.46s</li>
<li>adam: 약 41.29s</li>
</ol>
<ul>
<li>수렴 (train loss 확인)</li>
</ul>
<ol>
<li>adadelta
<img src="https://velog.velcdn.com/images/jup-hui/post/30eda12d-698f-457b-84e3-0a4d1a62d939/image.png" alt=""></li>
</ol>
<ul>
<li>약 batch 1000 이후로 수렴함</li>
</ul>
<ol start="2">
<li>adam
<img src="https://velog.velcdn.com/images/jup-hui/post/983e0a13-293c-4870-bb8f-4e771840740e/image.png" alt=""></li>
</ol>
<ul>
<li>약 batch 2000 이후로 수렴함</li>
</ul>
<h1 id="22-최종-모델-성능">2.2. 최종 모델 성능</h1>
<ol>
<li>adadelta (training loss: 0.000609, test loss: 0.0343, test accuracy: 9890/10000)</li>
<li>adam (training loss: 0.007123, test loss: 0.0316, test accuracy: 9902/10000)</li>
</ol>
<h1 id="23-매개변수-비교">2.3. 매개변수 비교</h1>
<p>첫번째 Convolution layer와 flatten 후 dense layer에서 parameter 차이가 크게 발생함. </p>
<pre><code>from copy import deepcopy

import torch
import torch.nn as nn
import torch.nn.functional as F
import torch.optim as optim
from torch.utils.data import DataLoader
from torchvision import datasets, transforms
import matplotlib.pyplot as plt
import time

class ConvNet(nn.Module): #nn.Module을 상속받아 기본적인 기능들을 사용할 수 있게 만듦 =&gt; nn.Moudle: 부모 클래스
    def __init__(self):
        super(ConvNet, self).__init__() # super().__init__() 으로 사용해도 같음. 클래스 이름 작성하는 건 python2 버전임
        # 1 in_channels : gray scale image, 16 out channels : 16 feature maps, # stride &lt; kernel_size * 0.1
        self.cn1 = nn.Conv2d(1, 16, 3, 1) # 1 in_channels := gray scale image.
        self.cn2 = nn.Conv2d(16, 32, 3, 1)
        # nn.Dropout: 주로 1차원에 사용. 모든 차원에 사용 가능.
        # 2D: 2D 데이터. 채널 단위로 드랍 아웃. 각 채널에 대해 동일한 위치에 있는 값을 동시에 드롭하기 때문에, 전체 채널이 드롭되거나 유지되는 방식입니다. 이를 통해 채널 간 상관관계를 보존할 수 있습니다.
        # 3D: 동영상. 특정 채널의 모든 프레임이나 볼륨이 드롭되기 때문에, 3D 데이터에서 특정 시퀀스나 채널이 온전히 제거되는 효과를 얻습니다.
        self.dp1 = nn.Dropout2d(0.10)
        self.dp2 = nn.Dropout2d(0.25)
        self.fc1 = nn.Linear(4608, 64) # 32개의 채널, 1개의 채널 = 12 X 12
        self.fc2 = nn.Linear(64, 10) # 10개의 class (classification 문제)

    def forward(self, x): # input 이미지의 해상도 28 X 28 X 1
        x = self.cn1(x) # 3 size kernel 적용 후 26 X 26 X 16
        x = F.relu(x)
        x = self.cn2(x) # 3 size kernel 적용 후 24 X 24 X 32
        x = F.relu(x)
        x = F.max_pool2d(x,2) # 2 size kernel 적용 후 12 X 12 X 32
        x = self.dp1(x)
        x = torch.flatten(x, 1) # 1 X (12 X 12 X 32)
        x = self.fc1(x) # 1 X 64
        x = F.relu(x)
        x = self.dp2(x)
        x = self.fc2(x) # 1 X 10
        op = F.log_softmax(x, dim=1) # softmax에 log 값 취함. gradient 구할 때 Nan 발생 막아주는 함수
        return op

# backpropagation
def train(model, device, train_dataloader, optim, epoch):
    model.train() # ConvNet class를 받아옴
    train_loss = []

    start_time = time.time()

    for b_i, (X, y) in enumerate(train_dataloader): # one epoch
        # (b_i = batch_idx)
        # print(f&quot;Batch {b_i + 1}: data shape = {X.shape}, target shape = {y.shape}&quot;)
        # Batch 1: data shape = torch.Size([32, 1, 28, 28]), target shape = torch.Size([32])
        X, y = X.to(device), y.to(device) # copy data

        optim.zero_grad() # optim (torch.optim) 최적화 알고리즘 기능을 담고 있음. SGD, Adam, RMSprop 등
        pred_prob = model(X)
        loss = F.nll_loss(pred_prob, y) # - log softmax
        loss.backward()
        optim.step()

        train_loss.append(loss.item())

        if b_i % 100 == 0: # every 10 batches
            print(&#39;epoch: {} [{}/{} ({:.0f}%)]\t training loss: {:.6f}&#39;.format(epoch, b_i, len(train_dataloader), 100.*b_i/len(train_dataloader), loss.item()))

    end_time = time.time()
    print(f&quot;Runtime: {end_time - start_time:.6f} seconds&quot;)

    return train_loss

def test(model, device, test_dataloader):
    model.eval() # 학습할 때만 필요한 Dropout, Batchnorm 등의 기능을 비활성화 하여 추론할 때의 모드로 작동
    loss, success = 0, 0
    with torch.no_grad(): # gradient calculation을 비활성화하여 메모리 소비를 제한함 (with은 파일이나 데이터베이스를 시작하고 자동 닫기/종료하는 기능)
        for X, y in test_dataloader:
            X, y = X.to(device), y.to(device)
            pred_prob = model(X)

            # 배치별 손실 합
            loss += F.nll_loss(pred_prob, y, reduction=&#39;sum&#39;).item()

            pred = pred_prob.argmax(dim=1, keepdim=True) # 500개의 데이터에 대한 라벨이 저장됨

            success += pred.eq(y.view_as(pred)).sum().item() # view_as : reshape

    loss /= len(test_dataloader.dataset)
    print(&#39;\nTest dataset: Overall Loss: {:.4f}, Overall Accuracy: {}/{} ({:.0f}%)\n&#39;.format(loss, success, len(test_dataloader.dataset), 100.*success/len(test_dataloader.dataset)))


# 평균값과 표준 편차 값은 훈련 데이터셋의 이미지 전체의 픽셀값 전체에 대한 평균으로 계산된다.
train_dataloader = torch.utils.data.DataLoader(
    datasets.MNIST(&#39;../data&#39;, train=True, download=True,
                   transform=transforms.Compose([transforms.ToTensor(), transforms.Normalize((0.1302,),(0.3069,))])),
    batch_size=32, shuffle= True
) # transforms.ToTensor() converts a PIL Image or Numpy array to a torch.Tensor and scales its pixel values to the range [0,1]

test_dataloader = torch.utils.data.DataLoader(
    datasets.MNIST(&#39;../data&#39;, train = False,
                   transform= transforms.Compose([transforms.ToTensor(), transforms.Normalize((0.1302,), (0.3069,))])),
    batch_size=500, shuffle=False
)

torch.manual_seed(0)
device = torch.device(&quot;cpu&quot;)

model_adadelta = ConvNet()
model_adam = deepcopy(model_adadelta)

optimizer_adadelta = optim.Adadelta(model_adadelta.parameters(), lr=0.5) # Adam 비교 report 제작
optimizer_adam = optim.Adam(model_adam.parameters(), lr=0.001)

# adadelta 로 학습
all_train_losses_adadelta = []
for epoch in range(1,6):
    train_losses = train(model_adadelta, device, train_dataloader, optimizer_adadelta, epoch)
    all_train_losses_adadelta+=train_losses
    test(model_adadelta, device, test_dataloader)

# adam으로 학습
all_train_losses_adam = []
for epoch in range(1,6):
    train_losses = train(model_adam, device, train_dataloader, optimizer_adam, epoch)
    all_train_losses_adam+=train_losses
    test(model_adam, device, test_dataloader)

# test_samples = enumerate(test_dataloader)
# b_i, (sample_data, sample_targets) = next(test_samples)

# plt.imshow(sample_data[0][0], cmap=&#39;gray&#39;, interpolation = &#39;none&#39;)
# print(f&quot;Model prediction is : {model(sample_data).data.max(1)[1][0]}&quot;)
# print(f&quot;Ground truth is : {sample_targets[0]}&quot;)

# 손실 값 시각화
# plt.figure(figsize = (10,6))
# plt.plot(all_train_losses, label=&#39;Training Loss&#39;)
# plt.xlabel(&#39;Batch Index&#39;)
# plt.ylabel(&#39;Loss&#39;)
# plt.title(&#39;Training Loss Over Batches&#39;)
# plt.legend()
# plt.show()

# 모델 파라미터 비교
for name, param_adadelta in model_adadelta.named_parameters():
    param_adam = dict(model_adam.named_parameters())[name]
    print(f&quot;Layer: {name}&quot;)
    # print(f&quot;SGD Parameter:\n{sum(param_sgd.data)}&quot;)
    # print(f&quot;Adam Parameter:\n{sum(param_adam.data)}&quot;)

    diff = torch.mean(param_adadelta.data - param_adam.data)
    print(f&quot;Difference:\n{diff}\n&quot;)

    norm_diff = (torch.max(param_adadelta) - diff)/(torch.max(param_adadelta) - torch.min(param_adadelta))
    print(f&quot;Normalized Difference:\n{norm_diff}\n&quot;)

# fc1.weight
# cn1.weight</code></pre>]]></description>
        </item>
        <item>
            <title><![CDATA[(진행중) 백준 2003번 수들의 합2]]></title>
            <link>https://velog.io/@jup-hui/%EC%A7%84%ED%96%89%EC%A4%91-%EB%B0%B1%EC%A4%80-2003%EB%B2%88-%EC%88%98%EB%93%A4%EC%9D%98-%ED%95%A92</link>
            <guid>https://velog.io/@jup-hui/%EC%A7%84%ED%96%89%EC%A4%91-%EB%B0%B1%EC%A4%80-2003%EB%B2%88-%EC%88%98%EB%93%A4%EC%9D%98-%ED%95%A92</guid>
            <pubDate>Sat, 26 Oct 2024 06:23:12 GMT</pubDate>
            <description><![CDATA[<h1 id="24-10-26">24-10-26</h1>
<pre><code>import sys
input = sys.stdin.readline

N,M = map(int,input().split())

seqs = list(map(int, input().split()))

ans = 0
start, end = 0, 1

while start &lt; N:


    if sum(seqs[start:end]) == M:
        ans += 1
        start += 1
        end = start + 1

    elif sum(seqs[start:end]) &lt; M:
        end +=1

        if end == N+1:
            start += 1
            end = start + 1

    else:
        start +=1
        end = start+1

print(ans)</code></pre><p>시간초과,,,, ㅠㅠㅠ two point 사용하는 문제
시작점을 하나씩 올려서 나머지 수열을 순차적으로 체크하는 방법</p>
<p>TO DO LIST
1 2 3 4 .. 수열이 있을 때,
1 + 2 + 3+ 4 &gt; 10
2 + 3, 2+ 3+ 4 처럼 반복해서 Sum을 진행하게 된다. 이를 극복해보자!</p>
<p>-&gt; HINT 이미 2472ms로 성공했음</p>
<p>+)
sum += a[right]
sum -= a[left]
를 활용해서 시컨스 전체를 sum하는 것을 줄이자! </p>
]]></description>
        </item>
        <item>
            <title><![CDATA[(진행중) [leetcode] 206.Reverse Linked List]]></title>
            <link>https://velog.io/@jup-hui/%EC%A7%84%ED%96%89%EC%A4%91-leetcode-206.Reverse-Linked-List</link>
            <guid>https://velog.io/@jup-hui/%EC%A7%84%ED%96%89%EC%A4%91-leetcode-206.Reverse-Linked-List</guid>
            <pubDate>Sun, 01 Sep 2024 11:23:46 GMT</pubDate>
            <description><![CDATA[<h1 id="24-09-01">24-09-01</h1>
<p>아직 ListNode 와 재귀 함수 사용법이 미숙함.. ㅠㅠ </p>
]]></description>
        </item>
        <item>
            <title><![CDATA[(진행중) [leetcode] 21 Merge Two Sorted List]]></title>
            <link>https://velog.io/@jup-hui/%EC%A7%84%ED%96%89%EC%A4%91-leetcode-21-Merge-Two-Sorted-List</link>
            <guid>https://velog.io/@jup-hui/%EC%A7%84%ED%96%89%EC%A4%91-leetcode-21-Merge-Two-Sorted-List</guid>
            <pubDate>Mon, 05 Aug 2024 13:18:38 GMT</pubDate>
            <description><![CDATA[<p>두 연결 리스트를 합치는 코드 작성</p>
<h1 id="24-08-05">24-08-05</h1>
<p>풀이 실패
Hint1. 재귀 구조 활용
Hint2. L1 = 1 -&gt; 2 -&gt; 3 일 때, L1.next는 1 -&gt; ? 를 의미한다. </p>
]]></description>
        </item>
        <item>
            <title><![CDATA[(진행중) [leetcode] 33 전화 번호 문자 조합]]></title>
            <link>https://velog.io/@jup-hui/%EC%A7%84%ED%96%89%EC%A4%91-leetcode-33-%EC%A0%84%ED%99%94-%EB%B2%88%ED%98%B8-%EB%AC%B8%EC%9E%90-%EC%A1%B0%ED%95%A9</link>
            <guid>https://velog.io/@jup-hui/%EC%A7%84%ED%96%89%EC%A4%91-leetcode-33-%EC%A0%84%ED%99%94-%EB%B2%88%ED%98%B8-%EB%AC%B8%EC%9E%90-%EC%A1%B0%ED%95%A9</guid>
            <pubDate>Tue, 30 Jul 2024 12:28:18 GMT</pubDate>
            <description><![CDATA[<p>번호마다 출력 가능한 문자열이 주어진다.
다수의 번호가 눌렸을 때, 화면에 표기될 수 있는 모든 경우의 문자열을 출력하는 문제이다. (물론, 하나의 번호가 눌리는 경우도 있다.)</p>
<h1 id="24-07-30">24-07-30</h1>
<pre><code>class Solution(object):

    def letterCombinations(self, digits):
        &quot;&quot;&quot;
        :type digits: str
        :rtype: List[str]
        &quot;&quot;&quot;

        dict = {&quot;2&quot;: &quot;abc&quot;, &quot;3&quot;:&quot;def&quot;, &quot;4&quot;:&quot;ghi&quot;, &quot;5&quot;:&quot;jkl&quot;, &quot;6&quot;:&quot;mno&quot;,&quot;7&quot;:&quot;pqrs&quot;,&quot;8&quot;:&quot;tuv&quot;,&quot;9&quot;:&quot;wxyz&quot;}

        if len(digits) &gt; 0:

            answer = [&quot;&quot;]

            for i in range(len(digits)):
                answer_ = []
                press_number = dict[digits[i]] 
                for letter in press_number:
                    answer_ += [ans + letter for ans in answer]
                answer = answer_

            return answer

        else: #empty input

            return []</code></pre><p>각 번호에 할당된 문자열을 리스트로 만들고,
새로운 번호가 눌렸을 때, 새로운 번호의 문자열 리스트와의 조합을 계산한다.</p>
<p>press 2 : [&#39;a&#39;, &#39;b&#39;, &#39;c&#39;]
press 3 : [&#39;ae&#39;, &#39;be&#39;, &#39;ce&#39; ,....]</p>
<p>run time은 20ms로, 꽤 길다.. </p>
<pre><code>class Solution(object):

    def letterCombinations(self, digits):
        &quot;&quot;&quot;
        :type digits: str
        :rtype: List[str]
        &quot;&quot;&quot;

         if digits == &quot;&quot;:
            return []

        dict = {&quot;2&quot;: &quot;abc&quot;, &quot;3&quot;:&quot;def&quot;, &quot;4&quot;:&quot;ghi&quot;, &quot;5&quot;:&quot;jkl&quot;, &quot;6&quot;:&quot;mno&quot;,&quot;7&quot;:&quot;pqrs&quot;,&quot;8&quot;:&quot;tuv&quot;,&quot;9&quot;:&quot;wxyz&quot;}

        answer = [&quot;&quot;]

        for digit in digits:
            answer = [ans + letter for letter in dict[digit] for ans in answer]

        return answer</code></pre><p>--&gt; 간결한 코드 버전! </p>
<ol>
<li>예외 케이스를 앞으로 빼면서 코드 전체 indent를 복잡하지 않게 정리함</li>
<li>answer_ 제거. (20ms -&gt; 17ms)
 answer_를 도입한 이유는 for문 돌면서 answer가 바뀌지 않도록 하는 장치였으나, 두 개의 for문을 inline으로 작성하면서 문제가 해결됨! </li>
</ol>
<p>To do list
DFS를 이용하자! 그래프 문제~~
모든 경우의 수를 DFS로 탐색하고 백트래킹으로 결과를 조합하면서 리턴하는 코드를 작성하세요. 
(Hint: 결과를 조합할 때는 v의 길이가 digits의 길이와 같을 때 return 합니다.)</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[(진행중) [백준] 1946번]]></title>
            <link>https://velog.io/@jup-hui/%EC%A7%84%ED%96%89%EC%A4%91-%EB%B0%B1%EC%A4%80-1946%EB%B2%88</link>
            <guid>https://velog.io/@jup-hui/%EC%A7%84%ED%96%89%EC%A4%91-%EB%B0%B1%EC%A4%80-1946%EB%B2%88</guid>
            <pubDate>Thu, 25 Jul 2024 13:40:54 GMT</pubDate>
            <description><![CDATA[<p>백준 1946번
각 입사 후보자들의 시험 점수를 주어준 후, 누군가의 하위호완이 되는 사람은 후보에서 제외한다.
시험 점수는 2종류이다. </p>
<h1 id="24-07-25">24-07-25</h1>
<pre><code>import sys
input = sys.stdin.readline

def n_safe(scores, people):

    answer = 1

    # sort w.r.t paper score rank
    sort_paper = sorted(scores)
    interview_rank_top_paper = sort_paper[0][1]

    if interview_rank_top_paper &lt; 3: # the case: top paper + top interview both. 
        return interview_rank_top_paper

    # sort w.r.t interview score rank
    sort_interview = sorted(sort_paper, key = lambda x:x[1])[:interview_rank_top_paper]

    for paper, interview in sort_interview[1:]:
        if paper &lt; sort_interview[0][0]:
            answer += 1

    return answer

n_problems = int(input())

answer = []
for problem in range(n_problems):
    people = int(input())

    scores = []
    for person in range(people):
        scores.append(list(map(int,input().split())))

    if people &gt; 1:
        answer.append(n_safe(scores,people))
    else:
        answer.append(1)    

print(&quot;\n&quot;.join(map(str,answer)))</code></pre><p>--&gt; 틀림</p>
<ol>
<li>input = sys.stdin.readline 작성없으면 시간초과</li>
<li>서류 심사 순으로 sort한 후 paper 순으로 sort하여 풀었으나, sort는 한번만 해도 된다. </li>
</ol>
]]></description>
        </item>
        <item>
            <title><![CDATA[(진행중) [leetcode] 200.Number of Islands]]></title>
            <link>https://velog.io/@jup-hui/%EC%A7%84%ED%96%89%EC%A4%91-leetcode-200.Number-of-Islands</link>
            <guid>https://velog.io/@jup-hui/%EC%A7%84%ED%96%89%EC%A4%91-leetcode-200.Number-of-Islands</guid>
            <pubDate>Fri, 28 Jun 2024 12:50:53 GMT</pubDate>
            <description><![CDATA[<p>1과 0으로 이루어진 list가 있다. 상하좌우로 연결된 1은 하나의 땅을 의미한다.
주어진 리스트에서 땅의 개수를 구하라. </p>
<h1 id="24-06-28-time-over">24-06-28 (Time Over.)</h1>
<pre><code>from collections import deque

class Solution(object):
    def numIslands(self, grid):
        &quot;&quot;&quot;
        :type grid: List[List[str]]
        :rtype: int
        &quot;&quot;&quot;

        self.grid = grid

        self.m = len(grid)
        self.n = len(grid[0])

        idxland = self.indexislands()
        searching_space = len(idxland)
        islands = 0
        discovered = []

        if searching_space &gt; 0:
            while len(idxland) &gt; 0:

                v = idxland.popleft()
                if not v in discovered:
                    islands +=1
                    discovered = self.DFS(v, discovered)

            return islands

        else:
            return islands

    def DFS(self, v, discovered = []):

          if not v in discovered:

            discovered.append(v)
            vx, vy = v

            adjacent = [(vx-1, vy), (vx, vy-1), (vx+1, vy), (vx, vy+1)]

            for adj in adjacent:

                if not adj in discovered:
                    adjx, adjy = adj

                    if adjx &lt; self.m and adjy &lt; self.n and adjx &gt;= 0 and adjy &gt;= 0:

                        if self.grid[adjx][adjy] == &quot;1&quot;:
                            self.DFS(adj,discovered)

            return discovered



    def indexislands(self):

        indislands = deque([])

        for m in range(self.m):
            for n in range(self.n):
                if self.grid[m][n] == &quot;1&quot;:
                    indislands.append((m,n))

        return indislands
</code></pre><p>DFS을 이용해서 &quot;연결된 땅&quot;을 정의하고자 했다.</p>
<ol>
<li>그래프 최상단 노드 구하기 : 주어진 리스트에서 1로 적힌 값의 index를 구함.</li>
<li>그래프 최상단 노드에서 각각 DFS 진행
 DFS 진행 시 좌우상하 4가지 노드를 연결노드로 진행.</li>
</ol>
<p>결과는 Time over..
1번의 과정을 생략하면 통과할 수 있을 것 같다.
주어진 리스트에서 1로 적힌 노드부터 DFS를 진행하여 마지막 m-1, n-1 값까지 searching 하는 것이다.</p>
<p>나의 코드에서는 discovered 라는 리스트로 탐색 구역을 저장했는데, &quot;1&quot; -&gt; &quot;0&quot;으로 변경하면서 탐색 구역을 체크하는 것이 좋을 것 같다 (저장 공간 절약)</p>
<p>Tip. 네 방향 각각 DFS 재귀를 사용하자. (파이썬 알고리즘 책 p.332)
-&gt; 왼쪽으로 탐색하는 DFS, 오른쪽으로 탐색하는 DFS, 등.. </p>
]]></description>
        </item>
        <item>
            <title><![CDATA[(진행중) [백준] 큐2]]></title>
            <link>https://velog.io/@jup-hui/%EC%A7%84%ED%96%89%EC%A4%91-%EB%B0%B1%EC%A4%80-%ED%81%902</link>
            <guid>https://velog.io/@jup-hui/%EC%A7%84%ED%96%89%EC%A4%91-%EB%B0%B1%EC%A4%80-%ED%81%902</guid>
            <pubDate>Sat, 22 Jun 2024 11:36:27 GMT</pubDate>
            <description><![CDATA[<p>백준 18258</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[(진행중) [백준] 예산]]></title>
            <link>https://velog.io/@jup-hui/%EC%A7%84%ED%96%89%EC%A4%91-%EB%B0%B1%EC%A4%80-%EC%98%88%EC%82%B0</link>
            <guid>https://velog.io/@jup-hui/%EC%A7%84%ED%96%89%EC%A4%91-%EB%B0%B1%EC%A4%80-%EC%98%88%EC%82%B0</guid>
            <pubDate>Sat, 22 Jun 2024 02:57:30 GMT</pubDate>
            <description><![CDATA[<p>백준 2512번
국가에서는 여러 지방에서 요청한 예산을 최대한 지급하려 한다. 하지만 국가의 총 예산이 제한되어 있기 때문에, 총 예산을 넘지 않는 선에서 요청 예산을 지급하기 위해 &quot;상한액&quot;을 정하여 상한액을 넘는 요청인 경우 상한액을 지급하기로 한다. 이 때, 배정된 예상 중 최대값을 프린트한다.</p>
<h1 id="24-06-22">24-06-22</h1>
<pre><code>N = int(input())

max_range = 0
money_list = []

for money in input().split(&quot; &quot;):
  money = int(money)
  max_range = max(money, max_range)
  money_list.append(money)

deposit = int(input())

if sum(money_list) &lt;= deposit:
  print(max_range)

else:
  condition = True
  small_range = int(deposit/N)
  max_range = min(max_range, deposit)

  while(condition):

    expectation, total = int((small_range + max_range)/2), 0

    for money in money_list:
      if money &lt; expectation:
        total += money
      else:
        total += expectation

    if (total == deposit):
      condition = False

    elif total &lt; deposit:
      small_range = expectation
      if max_range - small_range &lt; 2:
        condition = False

    elif total &gt; deposit:
      max_range = expectation

  print(expectation)

</code></pre><p>이분 탐색으로 잘 풀었지만, 코드의 가독성을 높힐 필요가 있다. </p>
<ol>
<li>while(left &lt;= right):
로 작성하자. 해당 구문을 사용하면 다른 작성자가 이분 탐색을 사용했구나 하고 읽기가 편하다.</li>
<li>middle = (left + right) // 2</li>
<li>left = middle + 1 또는 right = middle - 1 을 사용하여 무한 루프가 도는 것을 방지하자.</li>
</ol>
]]></description>
        </item>
        <item>
            <title><![CDATA[[백준] 2164 카드2]]></title>
            <link>https://velog.io/@jup-hui/%EB%B0%B1%EC%A4%80-2164-%EC%B9%B4%EB%93%9C2</link>
            <guid>https://velog.io/@jup-hui/%EB%B0%B1%EC%A4%80-2164-%EC%B9%B4%EB%93%9C2</guid>
            <pubDate>Sat, 15 Jun 2024 10:59:55 GMT</pubDate>
            <description><![CDATA[<p>N개의 순서대로 쌓여있는 카드 중 가장 앞 카드 한개를 버리고 그 다음 첫번째 카드를 가장 아래로 쌓는 과정은 N-1번 수행하여 마지막 남는 카드를 return 한다</p>
<h2 id="240615">240615</h2>
<pre><code>from collections import deque

N = int(input())

if N == 1:
  print(1)

else:
  cards = deque(list(range(1, N+1)))

  while len(cards) &gt; 1:
    discard = cards.popleft()
    topcard = cards.popleft()
    cards.append(topcard)

  print(cards[0])</code></pre><p>위 코드는 244ms 의 런타임이 소요되었다.</p>
<h2 id="240615-2">240615 (2)</h2>
<pre><code>from collections import deque

N = int(input())

if N == 1:
  print(1)

else:
  cards = deque(list(range(1, N+1)))

  for _ in range(1, N):
    discard = cards.popleft()
    cards.append(cards.popleft())

  print(cards[0])</code></pre><p>위 코드는 152ms 런타임이 소요되었다.</p>
<p>두 코드의 가장 큰 차이는 for/while 문 사용 차이이다.
while의 경우 condition 문을 N-1번 계산해야하기 때문에 시간 소요가 커진다. 
주어진 카드 개수에서 마지막 남은 카드 개수가 1개라는 점을 생각해보면, 버리는 행위는 N-1번으로 정해져 있다는 것을 알 수 있다. 
따라서 이번 문제에서는 for문 사용이 적합하다</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[(진행중) [leetcode] Palindrome Linked List]]></title>
            <link>https://velog.io/@jup-hui/%EC%A7%84%ED%96%89%EC%A4%91-leetcode-Palindrome-Linked-List</link>
            <guid>https://velog.io/@jup-hui/%EC%A7%84%ED%96%89%EC%A4%91-leetcode-Palindrome-Linked-List</guid>
            <pubDate>Wed, 10 Jan 2024 11:56:31 GMT</pubDate>
            <description><![CDATA[<p><a href="https://leetcode.com/problems/palindrome-linked-list/description/">https://leetcode.com/problems/palindrome-linked-list/description/</a></p>
<p>연결 리스트가 팰린드롬 구조인지 판별</p>
<h1 id="240110">240110</h1>
<p>리스트를 만들어 q.pop(0) != q.pop() 를 이용해 팰린드롬 구조를 판별하였으나
시간이 1220ms로 느린편이다.
이는 리스트의 경우 pop(0) 진행 시 모든 값이 한칸씩 시프팅 되기 때문에 시간 복잡도가 O(n)으로 발생하기 때문이다.</p>
<ol>
<li><p>양방향 모두 O(1)이 가능한 <strong>데크</strong>를 사용하자
 collection.deque()</p>
</li>
<li><p>!= None 보다 <strong>is not None</strong>이 더 빠르다</p>
</li>
<li><p>input이 []일 때도 고려하자</p>
</li>
<li><p>위 1~3 해결 후, 런너 기법 &amp; 다중 할당 &amp; 연결 리스트를 활용하여 문제해결하자 (p.210)</p>
</li>
</ol>
<pre><code># Definition for singly-linked list.
# class ListNode(object):
#     def __init__(self, val=0, next=None):
#         self.val = val
#         self.next = next


class Solution(object):
    def isPalindrome(self, head):
        &quot;&quot;&quot;
        :type head: ListNode
        :rtype: bool
        &quot;&quot;&quot;

        number_list = []

        while head.next != None:
            number_list.append(head.val)
            head = head.next

        number_list.append(head.val)

        while len(number_list) &gt; 1:
            if number_list.pop(0) != number_list.pop(-1):
                return False

        return True</code></pre>]]></description>
        </item>
        <item>
            <title><![CDATA[(진행중) [codeup] 캔디팡]]></title>
            <link>https://velog.io/@jup-hui/%EC%A7%84%ED%96%89%EC%A4%91-codeup-%EC%BA%94%EB%94%94%ED%8C%A1</link>
            <guid>https://velog.io/@jup-hui/%EC%A7%84%ED%96%89%EC%A4%91-codeup-%EC%BA%94%EB%94%94%ED%8C%A1</guid>
            <pubDate>Thu, 02 Jun 2022 06:13:05 GMT</pubDate>
            <description><![CDATA[<p>BFS를 이용하여 캔디팡 구현하기
<a href="https://codeup.kr/problem.php?id=2605">https://codeup.kr/problem.php?id=2605</a></p>
<h1 id="22-06-02">22-06-02</h1>
<p>BFS가 뭐지..?</p>
<p>Next what to do.</p>
<ol>
<li>from collections import deque 활용
 while queue 가 포인트라고 생각함.!</li>
</ol>
<h1 id="23-08-16">23-08-16</h1>
<p>BFS로 해결! &lt;- 검색함..</p>
<pre><code>import numpy as np
from collections import deque


candi_matrix =[]
n,m = 7,7

for i in range(n):
    candi_matrix.append(list(input().split(&quot; &quot;)))

Graph = {}

for i in range(n):
    for j in range(m):

        node = candi_matrix[i][j]

        connected_nodes = []
        if i &gt; 0:
            if candi_matrix[i-1][j] == node:
                connected_nodes.append((i-1,j))
        if j &gt; 0:
            if candi_matrix[i][j-1] == node:
                connected_nodes.append((i,j-1))
        if i &lt; n-1:
            if candi_matrix[i+1][j] == node:
                connected_nodes.append((i+1,j))
        if j &lt; m-1:
            if candi_matrix[i][j+1] == node:
                connected_nodes.append((i,j+1))

        if len(connected_nodes)&gt;0:
            Graph[(i,j)] = connected_nodes

 def bfs(G, start_point):
    visited = list() # 방문한 노드를 담을 배열
    queue = list() # 방문 예정인 노드를 담을 배열

    queue.append(start_point) # 처음에는 시작 노드 담아주고 시작하기.

    while queue: # 더 이상 방문할 노드가 없을 때까지.
        node = queue.pop(0) # 방문할 노드를 앞에서 부터 하나싹 꺼내기.

        if node not in visited: # 방문한 노드가 아니라면
            visited.append(node) # visited 배열에 추가
            queue.extend(Graph[node]) # 해당 노드의 자식 노드로 추가

    #print(&quot;bfs - &quot;, visited)

    return visited

visited_nodes = []
candi_pop = 0
while len(visited_nodes) &lt; len(Graph.keys()):


    start_point = list(set(Graph.keys())- set(visited_nodes))[0]
    connected_nodes = bfs(Graph,start_point)

    if len(connected_nodes) &gt;= 3:
        candi_pop += 1

    visited_nodes += list(set(connected_nodes) &amp; set(Graph.keys()))

print(candi_pop)</code></pre><p>Next what to do</p>
<ol>
<li>BFS 검색없이 사용! </li>
</ol>
]]></description>
        </item>
        <item>
            <title><![CDATA[[leetcode] Best Time to Buy and Sell Stock]]></title>
            <link>https://velog.io/@jup-hui/%EC%A7%84%ED%96%89%EC%A4%91-leetcode-Best-Time-to-Buy-and-Sell-Stock</link>
            <guid>https://velog.io/@jup-hui/%EC%A7%84%ED%96%89%EC%A4%91-leetcode-Best-Time-to-Buy-and-Sell-Stock</guid>
            <pubDate>Mon, 30 May 2022 11:23:23 GMT</pubDate>
            <description><![CDATA[<p>시간순으로 작성된 배열의 숫자들의 차이값 중 가장 큰 값을 구하라.
단, 나중 값에서 먼저 작성된 값을 빼야한다. 
<a href="https://leetcode.com/problems/best-time-to-buy-and-sell-stock/">https://leetcode.com/problems/best-time-to-buy-and-sell-stock/</a></p>
<h1 id="22-05-30">22-05-30</h1>
<pre><code>class Solution(object):
    def maxProfit(self, prices):
        &quot;&quot;&quot;
        :type prices: List[int]
        :rtype: int
        &quot;&quot;&quot;

        buy = 10000
        profit = 0
        n = len(prices)
        for i in range(0,n,2):
            if i == n-1:
                profit = max(profit,prices[i]-buy)
            else:
                j = i + 1
                profit = max(profit,prices[j]-prices[i],prices[j]-buy,prices[i]-buy)
                buy = min(buy,prices[i],prices[j])
            print(profit)
        return profit</code></pre><p>인덱스 두 개를 사용하여 시간 복잡도를 줄이고자 하였다.
1475ms로, 아쉬운 성능.</p>
<p>Next what to do.</p>
<ol>
<li>70ms 이하로 줄일 수 있다!</li>
</ol>
<h1 id="24-10-20">24-10-20</h1>
<pre><code>class Solution(object):
    def maxProfit(self, prices):
        &quot;&quot;&quot;
        :type prices: List[int]
        :rtype: int
        &quot;&quot;&quot;

        n = len(prices)

        if n == 1:
            return 0

        buy, profit = 10**(4), 0
        for i in range(n-1):
            buy = min(buy, prices[i])
            profit = max(profit, prices[i+1]-buy)

        return profit</code></pre><p>O(n)으로 해결함
run time - 114ms</p>
<p>이전 코드 보완 사항</p>
<ul>
<li>n == 1 예외 처리 진행</li>
<li>min &amp; max 사용 간소화</li>
</ul>
<p>Run time을 더 줄이고 싶다면?</p>
<ul>
<li>len(prices)를 사용하지 않고 진행하면 시간이 더 줄 수 있음</li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[(진행중) [leetcode] Product of Array Except Self]]></title>
            <link>https://velog.io/@jup-hui/%EC%A7%84%ED%96%89%EC%A4%91-leetcode-Product-of-Array-Except-Self</link>
            <guid>https://velog.io/@jup-hui/%EC%A7%84%ED%96%89%EC%A4%91-leetcode-Product-of-Array-Except-Self</guid>
            <pubDate>Mon, 30 May 2022 09:53:09 GMT</pubDate>
            <description><![CDATA[<p>자기 자신을 제외한 모든 원소들의 곱들을 산출하시오.
<a href="https://leetcode.com/problems/product-of-array-except-self/">https://leetcode.com/problems/product-of-array-except-self/</a></p>
<ul>
<li>단, 나눗셈을 하지 않고 O(n)에 풀이하시오.</li>
</ul>
<h1 id="22-05-30">22-05-30</h1>
<pre><code>import numpy as np

class Solution(object):
    def productExceptSelf(self, nums):
        &quot;&quot;&quot;
        :type nums: List[int]
        :rtype: List[int]
        &quot;&quot;&quot;
        answer = np.array([1]*len(nums))
        for i,n in enumerate(nums):
            multiplication = answer*n - answer
            multiplication[i] = 0
            answer += multiplication

        return answer
</code></pre><p>array로 각 원소의 곱만큼 더하기 방식으로 진행했다.
단, 해당 원소는 0을 더함으로 조건을 만족하였다.
하지만, Time Out. ㅎㅎ
array 자체로 계산하는 것이 O(n)...</p>
<p>Next to do.</p>
<ol>
<li>왼쪽 곱셈에 결과에 오른쪽 값을 차례대로 곱셈하는 방식으로 풀자 </li>
</ol>
<h1 id="24-09-11">24-09-11</h1>
<pre><code>import numpy as np 
class Solution(object):
    def productExceptSelf(self, nums):
        &quot;&quot;&quot;
        :type nums: List[int]
        :rtype: List[int]
        &quot;&quot;&quot;

        n = len(nums)

        answer = np.array([1]*n)

        for i, num in enumerate(nums):

            backup = answer[i]
            answer *= num
            answer[i] = backup

        return answer</code></pre><p>자기 자신에 해당하는 인덱스만 backup으로 남겨둔 후, 어레이의 모든 값에 숫자를 곱함.
그 이후 해당 인덱스에 backup 값으로 다시 대체함.  </p>
<p>Next What to Do</p>
<ol>
<li>2*O(n) 으로 푼다고 생각</li>
<li>정방향 O(n) + 역방향 O(n)</li>
</ol>
]]></description>
        </item>
        <item>
            <title><![CDATA[(진행중) [leetcode] Trapping Rain Water]]></title>
            <link>https://velog.io/@jup-hui/%EC%A7%84%ED%96%89%EC%A4%91-leetcode-Trapping-Rain-Water</link>
            <guid>https://velog.io/@jup-hui/%EC%A7%84%ED%96%89%EC%A4%91-leetcode-Trapping-Rain-Water</guid>
            <pubDate>Mon, 30 May 2022 04:32:22 GMT</pubDate>
            <description><![CDATA[<p>숫자 배열의 증가/감소 패턴을 인지하는 코드 생성
<a href="https://leetcode.com/problems/trapping-rain-water/">https://leetcode.com/problems/trapping-rain-water/</a> </p>
<h1 id="22-05-30">22-05-30</h1>
<p>fail.. 
스택쌓기로 풀었는데, 잘 안됨..</p>
<p>Next what to do</p>
<ol>
<li>투 포인터 사용
&#39;&#39;&#39;
So, we can set 2 pointers left_max,right_max and check which side is greater,if one side is greater iterate on other side because at the min side the water will be filled at its limit. and iterate till pointer is lower than the other one.
&#39;&#39;&#39;</li>
<li>1번 성공 시, 스택쌓기 재도전</li>
</ol>
<h1 id="24-09-10">24-09-10</h1>
<pre><code>class Solution(object):
    def trap(self, height):
        &quot;&quot;&quot;
        :type height: List[int]
        :rtype: int
        &quot;&quot;&quot;

        if len(height) &lt; 2 or min(height) == max(height):
            return 0

        water_left, water_right = [], []
        top_height_left, top_height_right = height[0], height[-1]

        for i in range(1,len(height)):

            left_gap,right_gap = top_height_left-height[i],top_height_right-height[len(height)-i]

            water_left.append(max(left_gap, 0))
            water_right.append(max(right_gap,0))

            top_height_left, top_height_right = max(top_height_left, height[i]), max(top_height_right, height[len(height)-i])

        water = 0
        for i in range(len(height)-1):
            water += min(water_left[i], water_right[len(height)-1-i-1])

        return water</code></pre><ol>
<li>왼쪽으로 슬라이딩 하면서 가장 높은 벽과 현재 벽의 차이 구함.</li>
<li>오른쪽으로 슬라이딩 하면서 1번과 유사하게 구함.</li>
<li>1번과 2번의 산출된 값 중에 작은 값이 water 높이임. </li>
</ol>
<p>Next what to do
좌우 포인터가 가운데로 점점 이동하여 만난다는 방향으로 코드 작성하기 </p>
]]></description>
        </item>
        <item>
            <title><![CDATA[(진행중) [leetcode] Longest Palindromic Substring]]></title>
            <link>https://velog.io/@jup-hui/%EC%A7%84%ED%96%89%EC%A4%91-leetcode-Longest-Palindromic-Substring</link>
            <guid>https://velog.io/@jup-hui/%EC%A7%84%ED%96%89%EC%A4%91-leetcode-Longest-Palindromic-Substring</guid>
            <pubDate>Wed, 25 May 2022 07:48:26 GMT</pubDate>
            <description><![CDATA[<p>최장 팰린드롬 문자열 찾기
<a href="https://leetcode.com/problems/longest-palindromic-substring/">https://leetcode.com/problems/longest-palindromic-substring/</a></p>
<h1 id="22-05-25">22-05-25</h1>
<pre><code>class Solution(object):
    def longestPalindrome(self, s):
        &quot;&quot;&quot;
        :type s: str
        :rtype: str
        &quot;&quot;&quot;
        n = len(s)

        for i in range(n-1):
            for j in range(0,i+1):
                ss = s[j:n-i+j]
                if ss == ss[::-1]:
                    return ss

        return s[0]</code></pre><p>Time Limit Exceeded
현재 코드 계산량은 $n(n-1)/2.$
abcdef.(중략).xx 이런 경우, xx를 찾기위해서 $O(n^2)$의 작업을 해야함. </p>
<p>Next what to do </p>
<ol>
<li>짝수(2)-홀수(3) 투 포인터 사용</li>
<li>작은 단위에서 확장하는 방식으로 코드 짜기 </li>
</ol>
<h1 id="24-09-10">24-09-10</h1>
<pre><code>class Solution(object):


    def longestPalindrome(self, s):
        &quot;&quot;&quot;
        :type s: str
        :rtype: str
        &quot;&quot;&quot;

        def findPalindrome(s):
            if s == s[::-1]:
                return True
            else:
                return False

        def updatepalindrome(s, start, end, condition = True):

            while (start &gt; 0) and (end &lt; n) and condition:
                if findPalindrome(s[start-1:end+1]):
                    start -= 1
                    end += 1
                else:
                    condition = False

            return start, end

        def searchingPalindrome(s, start, end, palindrome): 

            if findPalindrome(s[start:end]): 
                updated_start, updated_end = updatepalindrome(s, start, end)

                palindrome = s[updated_start:updated_end] if len(palindrome) &lt; (updated_end-updated_start) else palindrome

            return palindrome

        n = len(s)

        if n &lt; 2:
            return s

        palindrome = s[0]

        for i in range(n-1):

                # even searching
                start, end = i, i+2
                palindrome = searchingPalindrome(s, start, end, palindrome)

                # odd searching
                start, end = i, i+3
                palindrome = searchingPalindrome(s, start, end, palindrome)

        return palindrome</code></pre><ol>
<li>input 길이가 2보다 짧은 경우, 예외 처리 진행 </li>
<li>output을 주어진 인풋의 첫번째 글자로 시작함.</li>
<li>첫번째 글짜부터 길이가 짝수인 팰린드롬, 홀수인 팰린드롬을 확인하여 output에 업데이트 함.</li>
</ol>
<p>Next what to do</p>
<ol>
<li>빠르게 리턴하는 부분에서 한 글자인 경우, 전체 글자가 팰린드롬인 경우로 처리하자.</li>
<li>코드 가독성 높히기<ul>
<li>palindrome = max(palindrome, searchingPalindrome(i, i+2), searchingPalindrome(i, i+3), key=len) </li>
<li>line이 30줄 넘지 않도록 작성하자</li>
</ul>
</li>
<li>주의) 슬라이싱과 인덱스 조회에는 차이가 있다. 이를 잘 고려해서 작성할 것. </li>
</ol>
]]></description>
        </item>
        <item>
            <title><![CDATA[[leetcode] Group Anagrams]]></title>
            <link>https://velog.io/@jup-hui/leetcode-Group-Anagrams</link>
            <guid>https://velog.io/@jup-hui/leetcode-Group-Anagrams</guid>
            <pubDate>Wed, 25 May 2022 06:02:07 GMT</pubDate>
            <description><![CDATA[<p>애너그램별로 그룹 생성
<a href="https://leetcode.com/problems/group-anagrams/">https://leetcode.com/problems/group-anagrams/</a></p>
<h1 id="22-05-25">22-05-25</h1>
<pre><code>class Solution(object):
    def groupAnagrams(self, strs):
        &quot;&quot;&quot;
        :type strs: List[str]
        :rtype: List[List[str]]
        &quot;&quot;&quot;
        answer = dict()
        for str_ in strs:
            sort_str = &#39;&#39;.join(sorted(str_))
            if sort_str in answer.keys():
                answer[sort_str].append(str_)
            else:
                answer[sort_str] = [str_]

        return answer.values()</code></pre><ul>
<li>Runtime: 2817ms</li>
<li>Memory: 17.2MB</li>
</ul>
<p>Next what to do</p>
<ol>
<li>collections.defaultdict(list)를 이용하여 KeyError를 해결하자. &lt;- key 있는지 확인하는 것 자체가 시간이 오래 걸림 </li>
</ol>
<h2 id="24-06-29">24-06-29</h2>
<pre><code>import collections 
class Solution(object):
    def groupAnagrams(self, strs):
        &quot;&quot;&quot;
        :type strs: List[str]
        :rtype: List[List[str]]
        &quot;&quot;&quot;

        anangram = collections.defaultdict(list)
        for word in strs:
            key = &#39;&#39;.join(sorted(word))
            anangram[key].append(word)

        return anangram.values()</code></pre><p>이전코드에서 collections.defaultdict(list) 사용을 추가함.
런타임은 63ms로 1/4 가량 줄어듦.
현업에서도 collections.defaultdict()는 많이 사용하면 좋을 듯!</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[(진행중) [leetcode]  Valid Palindrome]]></title>
            <link>https://velog.io/@jup-hui/%EC%A7%84%ED%96%89%EC%A4%91-leetcode-Valid-Palindrome</link>
            <guid>https://velog.io/@jup-hui/%EC%A7%84%ED%96%89%EC%A4%91-leetcode-Valid-Palindrome</guid>
            <pubDate>Wed, 25 May 2022 02:17:21 GMT</pubDate>
            <description><![CDATA[<p>팰린드롬 확인하기
<a href="https://leetcode.com/problems/valid-palindrome/">https://leetcode.com/problems/valid-palindrome/</a></p>
<h1 id="22-05-25">22-05-25</h1>
<pre><code>class Solution(object):
    def isPalindrome(self, s):
        &quot;&quot;&quot;
        :type s: str
        :rtype: bool
        &quot;&quot;&quot;
        s = s.lower()
        alphanumeric = &#39;abcdefghijklmnopqrstuvwxyz0123456789&#39;
        processed_s = &#39;&#39;.join([alpha for alpha in s if alpha in alphanumeric])
        n = len(processed_s)

        for i in range(int(n/2)):
            if processed_s[i] != processed_s[n-1-i]:
                return False
        return True</code></pre><ul>
<li>Runtime: 58ms</li>
<li>Memory: 15.5MB</li>
</ul>
<p>Next what to do.</p>
<ol>
<li>정규식 사용하여 전처리 진행</li>
<li>슬라이싱을 이용하여 팰린드롬 확인하기</li>
</ol>
<h2 id="24-06-29">24-06-29</h2>
<p>[::-1] 로 string을 거꾸로 뒤집을 수 있다. </p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[백준] 로프]]></title>
            <link>https://velog.io/@jup-hui/%EC%A7%84%ED%96%89%EC%A4%91-%EB%B0%B1%EC%A4%80-%EB%A1%9C%ED%94%84</link>
            <guid>https://velog.io/@jup-hui/%EC%A7%84%ED%96%89%EC%A4%91-%EB%B0%B1%EC%A4%80-%EB%A1%9C%ED%94%84</guid>
            <pubDate>Tue, 24 May 2022 14:34:05 GMT</pubDate>
            <description><![CDATA[<p><a href="https://www.acmicpc.net/problem/2217">https://www.acmicpc.net/problem/2217</a></p>
<h1 id="22-05-24">22-05-24</h1>
<pre><code>N = int(input())
ropes = sorted([int(input()) for _ in range(N)],reverse = True)

answer = 0
while(ropes):
    answer = max(answer,ropes[-1]*len(ropes))
    ropes.pop()

print(answer)</code></pre><p>Time cost가 있음 왜일까~ 
max = O(n)이기 때문에 루프안에서 max 사용하는 것이 좋지 않음</p>
<h1 id="24-06-21">24-06-21</h1>
<pre><code>import sys

N = int(input())

rope_list = {}
for _ in range(N):
  rope = int(sys.stdin.readline())
  if rope in rope_list.keys():
    rope_list[rope] += 1
  else:
    rope_list[rope] = 1

sorted_rope_list = sorted(rope_list, reverse = True)

big_rope = sorted_rope_list[0]
n_rope = rope_list[big_rope]
answer = big_rope * n_rope
for key in sorted_rope_list[1:]:
  n_rope += rope_list[key]
  answer = max(answer, key*n_rope)

print(answer)
</code></pre><p>import sys
sys.stdin.readline()
으로 input을 받으면 속도가 많이 개선된다!</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[백준] 단어 수학]]></title>
            <link>https://velog.io/@jup-hui/%EC%A7%84%ED%96%89%EC%A4%91%EB%B0%B1%EC%A4%80-%EB%8B%A8%EC%96%B4-%EC%88%98%ED%95%99</link>
            <guid>https://velog.io/@jup-hui/%EC%A7%84%ED%96%89%EC%A4%91%EB%B0%B1%EC%A4%80-%EB%8B%A8%EC%96%B4-%EC%88%98%ED%95%99</guid>
            <pubDate>Tue, 24 May 2022 09:28:30 GMT</pubDate>
            <description><![CDATA[<p>알파벳에 숫자를 부여하여 최대 결과값을 산출하는 조합을 찾기
1339번 문제</p>
<h1 id="22-05-24">22-05-24</h1>
<pre><code>N = int(input())
alphabet,count_apb = [&#39;&#39;]*9,&#39;&#39;
for _ in range(N):
    for i,a in enumerate(input()[::-1]):
        alphabet[8-i] += a
        count_apb += a*(i+1)

answer,number_hash,number = 0, {}, 9
for i,apb in enumerate(alphabet):
    for a in sorted(apb,key = lambda x : count_apb.count(x), reverse = True):
        if a not in number_hash.keys():
            number_hash[a] = number
            number -= 1
        answer += number_hash[a]*(10**(8-i))

print(answer)</code></pre><p>fail..
단어가 위치한 자리가 높은 십의 자리일 수록 높은 숫자를 부여하는 코드를 작성</p>
<p>반례) ABB/ BB 9회 반복
A : 8
B : 9</p>
<h1 id="24-06-21">24-06-21</h1>
<pre><code>N = int(input())

char = {}
for _ in range(N):

  input_char = input()
  digits = len(input_char) # 자리수 확인

  for ic in input_char:
    if ic in char.keys():
      char[ic] += 10**(digits-1)
    else:
      char[ic] = 10**(digits-1)

    digits -= 1

sorted_char = sorted(char, key = lambda x: char[x], reverse = True)

answer = 0
iter = 0
for alphabet in sorted_char:
  answer += char[alphabet]*(9-iter)
  iter += 1

print(answer)
</code></pre><p>key point는 알파벳마다 자리수를 고려해 모두 더하고 더한 값의 대소를 비교하여, 가장 큰 값을 가진 알파벳부터 9를 부여하는 것이다. 
AAA / BAC 이렇게 인풋이 주어진 경우, A = 100 + 10 + 1 + 10 = 121, B = 100, C = 1 이므로 A, B, C 순으로 9,8,7을 부여하여 9<em>121 + 8</em>100 + 7*1 의 답을 리턴한다. </p>
]]></description>
        </item>
    </channel>
</rss>