<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:content="http://purl.org/rss/1.0/modules/content/"><channel><title>Greedy on Kelly Dev</title><link>https://kelly-chui.github.io/algorithmtags/greedy/</link><description>Recent content in Greedy on Kelly Dev</description><generator>Hugo</generator><language>en-us</language><lastBuildDate>Sat, 15 Aug 2026 12:48:53 +0900</lastBuildDate><atom:link href="https://kelly-chui.github.io/algorithmtags/greedy/index.xml" rel="self" type="application/rss+xml"/><item><title>Codeforces 276C. Little Girl and Maximum Sum</title><link>https://kelly-chui.github.io/ps/2026/ps-codeforces-276c-little-girl-and-maximum-sum/</link><pubDate>Sat, 15 Aug 2026 12:48:53 +0900</pubDate><guid>https://kelly-chui.github.io/ps/2026/ps-codeforces-276c-little-girl-and-maximum-sum/</guid><description>&lt;h2 id="문제"&gt;문제&lt;/h2&gt;
&lt;p&gt;&lt;a href="https://codeforces.com/problemset/problem/276/C"&gt;https://codeforces.com/problemset/problem/276/C&lt;/a&gt;&lt;/p&gt;
&lt;h2 id="풀이"&gt;풀이&lt;/h2&gt;
&lt;p&gt;크기 &lt;code&gt;n&lt;/code&gt;인 수열 &lt;code&gt;a&lt;/code&gt;와 쿼리 &lt;code&gt;q&lt;/code&gt;개가 주어진다. 각 쿼리는 인덱스 $[l, r]$ 범위를 지정하며, 해당 범위의 원소 합을 구한다. 수열 &lt;code&gt;a&lt;/code&gt;를 적절히 재배열하여 모든 쿼리의 합의 총합을 최대화 한 수를 출력하면 된다.&lt;/p&gt;
&lt;p&gt;쿼리가 여러번 나오고 어떤 원소들은 쿼리 안에 중복되어서 포함되어 있을 수 있다. 쿼리의 범위 안에 가장 많이 포함된 원소의 순서대로, 높은 값을 배치하는 정렬 문제로 환원된다.&lt;/p&gt;
&lt;p&gt;어떤 원소 $a_i$가 쿼리 내부에 포함되어 있는지를 일반적으로 판단하게 되면 $O(q \times n)$이 되는데, &lt;code&gt;q&lt;/code&gt;, &lt;code&gt;n&lt;/code&gt;의 범위가 $1 \leq q 2 \times 10^5$ 이므로, 시간 안에 문제를 해결하기 어려워진다.&lt;/p&gt;</description></item><item><title>LeetCode 3302. Find the Lexicographically Smallest Valid Sequence</title><link>https://kelly-chui.github.io/ps/2026/ps-leetcode-3302-find-the-lexicographically-smallest-valid-sequence/</link><pubDate>Sat, 08 Aug 2026 21:06:44 +0900</pubDate><guid>https://kelly-chui.github.io/ps/2026/ps-leetcode-3302-find-the-lexicographically-smallest-valid-sequence/</guid><description>&lt;h2 id="문제"&gt;문제&lt;/h2&gt;
&lt;p&gt;&lt;a href="https://leetcode.com/problems/find-the-lexicographically-smallest-valid-sequence"&gt;https://leetcode.com/problems/find-the-lexicographically-smallest-valid-sequence&lt;/a&gt;&lt;/p&gt;
&lt;h2 id="풀이"&gt;풀이&lt;/h2&gt;
&lt;p&gt;&lt;code&gt;word1&lt;/code&gt;에서 인덱스를 고르고, 그 문자들로 &lt;code&gt;word2&lt;/code&gt;를 만들면 된다. 선택한 문자는 순서를 유지해야 하고, &lt;code&gt;word1&lt;/code&gt;의 문자 중 최대 하나는 다른 문자로 바꿔서 사용할 수 있다. 가능한 수열 중 인덱스가 사전순으로 가장 작은 것을 구하면 된다.&lt;/p&gt;
&lt;p&gt;앞에서부터 무조건 현재 문자가 같은지 확인하면서 고르면 되지만, 문자가 다른 위치에서 변경 기회를 바로 사용해도 뒤쪽에 남은 문자를 모두 맞출 수 있는지 확인해야 한다. 즉, 현재 위치를 선택했을 때 남은 문자의 개수가 충분해야 한다.&lt;/p&gt;</description></item><item><title>Codeforces 489C. Given Length and Sum of Digits</title><link>https://kelly-chui.github.io/ps/2026/ps-codeforces-489c-given-length-and-sum-of-digits/</link><pubDate>Thu, 06 Aug 2026 13:40:23 +0900</pubDate><guid>https://kelly-chui.github.io/ps/2026/ps-codeforces-489c-given-length-and-sum-of-digits/</guid><description>&lt;h2 id="문제"&gt;문제&lt;/h2&gt;
&lt;p&gt;&lt;a href="https://codeforces.com/problemset/problem/489/C"&gt;https://codeforces.com/problemset/problem/489/C&lt;/a&gt;&lt;/p&gt;
&lt;h2 id="풀이"&gt;풀이&lt;/h2&gt;
&lt;p&gt;자리수가 &lt;code&gt;m&lt;/code&gt;이고 각 자리수의 합이 &lt;code&gt;s&lt;/code&gt;인 정수 중 가장 큰 수와 가장 작은 수를 찾는 문제이다.&lt;/p&gt;
&lt;p&gt;처음에는 DP로 접근했는데, DP로는 수의 개수 정도만 구할 수 있고, 최대값과 최소값을 찾기는 힘들 것 같았다. 그래서 다시 그리디로 접근했다.&lt;/p&gt;
&lt;p&gt;자리수가 &lt;code&gt;m&lt;/code&gt;인데 $1 &amp;lt;= m &amp;lt;= 100$ 이기 때문에, &lt;code&gt;int&lt;/code&gt; 타입으로 수를 다루는건 쉽지 않고, 배열이나 벡터로 다루는게 더 쉽다.&lt;/p&gt;
&lt;p&gt;최대값은 계수가 높은 쪽에 큰 숫자를 배치하고, 최소값은 계수가 낮은 쪽에 큰 숫자를 배치하는 방법을 사용하자.&lt;/p&gt;</description></item><item><title>Leetcode 3014. Minimum Numbers of Pushes to Type Word I</title><link>https://kelly-chui.github.io/ps/2026/ps-leetcode-3014-minimum-numbers-of-pushes-to-type-word-i/</link><pubDate>Thu, 30 Jul 2026 22:58:21 +0900</pubDate><guid>https://kelly-chui.github.io/ps/2026/ps-leetcode-3014-minimum-numbers-of-pushes-to-type-word-i/</guid><description>&lt;h2 id="문제"&gt;문제&lt;/h2&gt;
&lt;p&gt;&lt;a href="https://leetcode.com/problems/minimum-number-of-pushes-to-type-word-i"&gt;https://leetcode.com/problems/minimum-number-of-pushes-to-type-word-i&lt;/a&gt;&lt;/p&gt;
&lt;h2 id="풀이"&gt;풀이&lt;/h2&gt;
&lt;p&gt;휴대전화의 2에서 8까지의 숫자에 문자를 배치할 수 있고, 2개 이상의 수가 배치되었을 땐 여러번 눌러야 뒤에 있는 숫자를 타이핑 할 수 있다. 스트링 &lt;code&gt;word&lt;/code&gt;가 주어졌을 때, 버튼을 가장 적게 눌러 &lt;code&gt;word&lt;/code&gt;를 타이핑 했을 때의 타이핑 수를 리턴하면 된다.&lt;/p&gt;
&lt;p&gt;각 키의 첫 번째 문자는 1번, 두 번째는 2번&amp;hellip; 눌러야 하므로 많이 등장하는 문자일수록 누름 횟수가 적은 앞자리에 배치해야 한다.&lt;/p&gt;
&lt;p&gt;빈도수 내림차순 정렬 후, 인덱스를 8로 나눈 몫 + 1이 해당 문자의 누름 횟수가 된다.&lt;/p&gt;</description></item><item><title>LeetCode 3518. Smallest Palindromic Rearrangement II</title><link>https://kelly-chui.github.io/ps/2026/ps-leetcode-3518-smallest-palindromic-rearrangement-ii/</link><pubDate>Wed, 29 Jul 2026 10:36:59 +0900</pubDate><guid>https://kelly-chui.github.io/ps/2026/ps-leetcode-3518-smallest-palindromic-rearrangement-ii/</guid><description>&lt;h2 id="문제"&gt;문제&lt;/h2&gt;
&lt;p&gt;&lt;a href="https://leetcode.com/problems/smallest-palindromic-rearrangement-ii"&gt;https://leetcode.com/problems/smallest-palindromic-rearrangement-ii&lt;/a&gt;&lt;/p&gt;
&lt;h2 id="풀이"&gt;풀이&lt;/h2&gt;
&lt;p&gt;&lt;a href="https://kelly-chui.github.io/ps/2026/ps-leetcode-3517-smallest-palindromic-rearrangement-i/"&gt;1번 문제&lt;/a&gt;와 마찬가지로 팰린드롬의 성질상 절반만 결정하면 전체가 결정된다. 따라서 이 문제는 절반 문자열의 &lt;code&gt;k&lt;/code&gt;번째 사전순 순열을 구하는 문제로 단순화된다.&lt;/p&gt;
&lt;p&gt;각 문자의 등장 횟수를 세고, 홀수 번 등장하는 문자는 팰린드롬의 가운데에 배치한다. 나머지는 2로 나눠 &lt;code&gt;halfTable&lt;/code&gt;을 만든다. 절반 문자열에는 중복 문자가 있을 수 있으므로, 전체 순열 수는 단순히 $n!$이 아니라 중복 순열 공식으로 구해야 한다.&lt;/p&gt;
&lt;p&gt;$$\frac{n!}{\prod_{i} n_i!}$$&lt;/p&gt;
&lt;p&gt;여기서 &lt;code&gt;n&lt;/code&gt;은 절반 문자열의 길이, &lt;code&gt;n_i&lt;/code&gt;는 각 문자의 개수이다. 이 값이 &lt;code&gt;k&lt;/code&gt;보다 작으면 &lt;code&gt;k&lt;/code&gt;번째 순열이 존재하지 않으므로 빈 문자열을 반환한다.&lt;/p&gt;</description></item><item><title>LeetCode 3499. Maximize Active Section With Trade I</title><link>https://kelly-chui.github.io/ps/2026/ps-leetcode-3499-maximize-active-section-with-trade-i/</link><pubDate>Tue, 21 Jul 2026 10:29:30 +0900</pubDate><guid>https://kelly-chui.github.io/ps/2026/ps-leetcode-3499-maximize-active-section-with-trade-i/</guid><description>&lt;h2 id="문제"&gt;문제&lt;/h2&gt;
&lt;p&gt;&lt;a href="https://leetcode.com/problems/maximize-active-section-with-trade-i"&gt;https://leetcode.com/problems/maximize-active-section-with-trade-i&lt;/a&gt;&lt;/p&gt;
&lt;h2 id="풀이"&gt;풀이&lt;/h2&gt;
&lt;p&gt;&lt;code&gt;'0'&lt;/code&gt;와 &lt;code&gt;'1'&lt;/code&gt;로만 이루어진 문자열 &lt;code&gt;s&lt;/code&gt;가 존재하고, 문제에서 주어진 연산을 최대 1번 적용하여 문자열에 있는 &lt;code&gt;'1'&lt;/code&gt;의 개수를 최대로 만든 뒤 그 개수를 리턴하면 된다.&lt;/p&gt;
&lt;p&gt;주어진 연산은 다음과 같다. (순서대로 둘 다 적용해야 한다.)&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;양 옆이 &lt;code&gt;'0'&lt;/code&gt;로 둘러싸인 연속된 &lt;code&gt;'1'&lt;/code&gt; 블록 하나를 선택해서 모두 &lt;code&gt;'0'&lt;/code&gt;로 바꾼다.&lt;/li&gt;
&lt;li&gt;양 옆이 &lt;code&gt;'1'&lt;/code&gt;으로 둘러싸인 연속된 &lt;code&gt;'0'&lt;/code&gt; 블록 하나를 선택해서 모두 &lt;code&gt;'1'&lt;/code&gt;으로 바꾼다.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;문제에서 &lt;code&gt;s&lt;/code&gt;의 양 옆에 &lt;code&gt;'1'&lt;/code&gt;을 붙이라 했는데, 이때 추가된 &lt;code&gt;'1'&lt;/code&gt;은 최종 반환값에 포함되지 않는다.&lt;/p&gt;</description></item><item><title>Programmers. 단속 카메라</title><link>https://kelly-chui.github.io/ps/2025/ps-programmers-speed-camera/</link><pubDate>Mon, 21 Jul 2025 00:00:00 +0000</pubDate><guid>https://kelly-chui.github.io/ps/2025/ps-programmers-speed-camera/</guid><description>&lt;h2 id="문제"&gt;문제&lt;/h2&gt;
&lt;p&gt;&lt;a href="https://school.programmers.co.kr/learn/courses/30/lessons/42884"&gt;https://school.programmers.co.kr/learn/courses/30/lessons/42884&lt;/a&gt;&lt;/p&gt;
&lt;h2 id="풀이"&gt;풀이&lt;/h2&gt;
&lt;p&gt;그리디 문제다. 그리디는 따로 정석 구현이 있는 알고리즘이 아니라 일종의 컨셉이지만, 배열 + 그리디면 잘 알다시피 정렬이 중요한 경우가 많다.&lt;/p&gt;
&lt;p&gt;단순하게 생각해보자, 문제에서 주어지는 것은 시작 위치와 종료 위치다. 그냥 종료하는 위치를 기준으로 오름차순 정렬한 후에 앞에서부터 탐색을 한다.&lt;/p&gt;
&lt;p&gt;현재 자동차의 종료 위치에 카메라를 설치하고, 다음 자동차를 살펴본다. 다음 자동차의 시작 위치가 이전 자동차의 종료 위치(즉 카메라가 설치된 위치)보다 앞에 있으면 다음 자동차도 설치된 카메라를 만나게 된다. 그렇지 않다면 또 그 자동차의 종료 위치에 카메라를 설치하면 된다.&lt;/p&gt;</description></item><item><title>BOJ 1049. 기타줄</title><link>https://kelly-chui.github.io/ps/2023/ps-boj-1049-guitar-strings/</link><pubDate>Fri, 16 Jun 2023 00:00:00 +0000</pubDate><guid>https://kelly-chui.github.io/ps/2023/ps-boj-1049-guitar-strings/</guid><description>&lt;h2 id="문제"&gt;문제&lt;/h2&gt;
&lt;p&gt;&lt;a href="https://www.acmicpc.net/problem/1049"&gt;https://www.acmicpc.net/problem/1049&lt;/a&gt;&lt;/p&gt;
&lt;h2 id="풀이"&gt;풀이&lt;/h2&gt;
&lt;p&gt;6개 묶음 패키지의 가격과 낱개의 가격이 각각 여러 개가 주어졌을 때, 가장 적은 비용으로 n개 이상의 수를 채워야 하는 문제이다.&lt;/p&gt;
&lt;p&gt;문제의 알고리즘은 다음과 같다.&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;패키지의 가격과 낱개의 가격이 같이 들어오므로 현재 가장 싼 패키지와 낱개의 가격과, 입력으로 들어온 가격을 각각 비교해서 갱신한다.&lt;/li&gt;
&lt;li&gt;패키지만 샀을때, 낱개만 샀을때, 패키지와 낱개를 동시에 샀을때 세가지 경우를 비교해서 가장 비용이 낮은 값을 출력한다.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;이 문제에서 구매 수량에 제한을 두지 않았으므로, 굳이 배열을 만들고 정렬을 할 필요가 없다. 패키지든 낱개든 무조건 가장 싼 가격만 알고 있으면 된다.&lt;/p&gt;</description></item><item><title>BOJ 11000. 강의실 배정</title><link>https://kelly-chui.github.io/ps/2023/ps-boj-11000-classroom-assignment/</link><pubDate>Fri, 16 Jun 2023 00:00:00 +0000</pubDate><guid>https://kelly-chui.github.io/ps/2023/ps-boj-11000-classroom-assignment/</guid><description>&lt;h2 id="문제"&gt;문제&lt;/h2&gt;
&lt;p&gt;&lt;a href="https://www.acmicpc.net/problem/11000"&gt;https://www.acmicpc.net/problem/11000&lt;/a&gt;&lt;/p&gt;
&lt;h2 id="풀이"&gt;풀이&lt;/h2&gt;
&lt;p&gt;정렬 후 그리디를 수행하는 전형적인 그리디 알고리즘 문제이다.&lt;/p&gt;
&lt;p&gt;강의가 시작하는 시간과 끝나는 시간이 주어져 있으므로 배열에 입력으로 주어진 시간들을 저장한 다음에 정렬해서, 강의가 가장 많은 시간의 강의 수를 출력하면 된다.&lt;/p&gt;
&lt;p&gt;알고리즘을 글로 표현하면 다음과 같다.&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;수업이 시작하는 시간과 끝나는 시간을 배열 &lt;code&gt;lecture&lt;/code&gt;에 저장한다. 이때 배열은 &lt;code&gt;[(Int, Bool)]&lt;/code&gt; 타입이며, &lt;code&gt;Int&lt;/code&gt;에는 시간, &lt;code&gt;Bool&lt;/code&gt;에는 강의가 시작하는 시간일 경우 &lt;code&gt;true&lt;/code&gt;, 끝나는 시간일 경우 &lt;code&gt;false&lt;/code&gt;를 저장한다.&lt;/li&gt;
&lt;li&gt;배열 &lt;code&gt;lecture&lt;/code&gt;를 정렬한다.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;lecture&lt;/code&gt;를 for 반복문으로 전체 순회한다. 튜플의 두 번째 원소가 &lt;code&gt;true&lt;/code&gt;인 경우 현재 진행 중인 강의 수를 저장하는 변수 &lt;code&gt;current&lt;/code&gt;의 값을 1 더한다. &lt;code&gt;false&lt;/code&gt;인 경우 강의가 끝난 것 이므로 변수 &lt;code&gt;current&lt;/code&gt;의 값을 1 뺀다.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;이때, 배열 lecture를 시간순으로만 정렬하게 되면 문제에서 다음과 같은 부분 때문에 문제가 생긴다.&lt;/p&gt;</description></item></channel></rss>