<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0">
  <channel>
    <title>Swift Library</title>
    <link>https://swift-library.tistory.com/</link>
    <description></description>
    <language>ko</language>
    <pubDate>Wed, 8 Jul 2026 11:26:47 +0900</pubDate>
    <generator>TISTORY</generator>
    <ttl>100</ttl>
    <managingEditor>Swift librarian</managingEditor>
    <image>
      <title>Swift Library</title>
      <url>https://tistory1.daumcdn.net/tistory/6619623/attach/50d5332495ce497e983718acda707270</url>
      <link>https://swift-library.tistory.com</link>
    </image>
    <item>
      <title>[Algorithm] LeetCode - Search in Rotated Sorted Array</title>
      <link>https://swift-library.tistory.com/242</link>
      <description>&lt;h2 data-ke-size=&quot;size26&quot;&gt;  문제&lt;/h2&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;a href=&quot;https://leetcode.com/problems/search-in-rotated-sorted-array/&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;Search in Rotated Sorted Array&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;난이도 &lt;span style=&quot;color: #f89009;&quot;&gt;&lt;b&gt;Medium&lt;/b&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;정렬되었지만 n칸 밀린 Array에서 target값이 존재하는지 확인하는 문제 (시간복잡도 log n 제한)&lt;/li&gt;
&lt;/ul&gt;
&lt;pre id=&quot;code_1747644513035&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;Example 1:
	Input: nums = [4,5,6,7,0,1,2], target = 0
	Output: 4

Example 2:
	Input: nums = [4,5,6,7,0,1,2], target = 3
	Output: -1&lt;/code&gt;&lt;/pre&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;  풀이&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;시간복잡도가 log n 이기 때문에 이진탐색이 생각났다. 결국 왼쪽을 탐색할지 오른쪽을 탐색해야 할지 결정하는 기준을 세우는 문제이다. 아래까지는 거의 모든 이진탐색이 비슷하게 시작할 것이라 생각된다.&lt;/p&gt;
&lt;pre id=&quot;code_1747644717871&quot; class=&quot;swift&quot; data-ke-language=&quot;swift&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;func search(_ nums: [Int], _ target: Int) -&amp;gt; Int {
    var left = 0
    var right = nums.count - 1

    while left &amp;lt; right {
        let mid = (left + right) / 2&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;문제는 &lt;b&gt;[0,1,2,3,4,5,6,7,8]&lt;/b&gt; 처럼 정렬이 잘 되어있으면 찾으면 되는데... &lt;b&gt;[3,4,5,6,7,8,0,1,2]&lt;/b&gt; 처럼 몇 칸 밀려있을 때가 문제이다. 그것을 아래와 같이 left가 mid보다 작거나 같다면 왼쪽이 정렬되어 있어 정렬되어 있는 왼쪽부터 검증을 시도하고, 그렇지 않다면 오른쪽이 정렬되어 있다는 뜻이니 오른쪽부터 검증을 시도하였다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;여기서 left가 mid보다 작기만 하면 되는 거 아닌가?라고 할 수도 있지만 &lt;b&gt;left == mid&lt;/b&gt; 일 경우이다. left가 3이고 right가 4일 경우라고 해보자 &lt;b&gt;[4,5,6,7,8,0,1,2,3]&lt;/b&gt; 일 경우 3, 4 인덱스만 뽑아보면 [8,0]인데 [8]은 정렬되어 있지만 [8, 0]은 정렬되어 있지 않다. 결국 left가 mid와 같다면 &lt;b&gt;nums[left] &amp;lt; nums[mid]&lt;/b&gt; 이면 무조건 오른쪽이 정렬이 된다고 판단하기 때문에 보다 작거나 같다는 조건이 필요하다.&lt;/p&gt;
&lt;pre id=&quot;code_1747644865376&quot; class=&quot;swift&quot; data-ke-language=&quot;swift&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;        if nums[left] &amp;lt;= nums[mid] { /// 왼쪽이 정렬되어 있음
            if nums[left]...nums[mid] ~= target {
                right = mid - 1
            } else {
                left = mid + 1
            }
        } else { /// 오른쪽이 정렬되어 있음
            if nums[mid]...nums[right] ~= target {
                left = mid + 1
            } else {
                right = mid - 1
            }
        }&lt;/code&gt;&lt;/pre&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;  결과&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;전체 코드는 아래와 같고 가장 빠른 속도가 나왔다.&lt;/p&gt;
&lt;pre id=&quot;code_1747644630383&quot; class=&quot;swift&quot; data-ke-language=&quot;swift&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;func search(_ nums: [Int], _ target: Int) -&amp;gt; Int {
    var left = 0
    var right = nums.count - 1

    while left &amp;lt; right {
        let mid = (left + right) / 2

        if nums[mid] == target { return mid }

        if nums[left] &amp;lt;= nums[mid] { /// 왼쪽이 정렬되어 있음
            if nums[left]...nums[mid] ~= target {
                right = mid - 1
            } else {
                left = mid + 1
            }
        } else { /// 오른쪽이 정렬되어 있음
            if nums[mid]...nums[right] ~= target {
                left = mid + 1
            } else {
                right = mid - 1
            }
        }
    }

    return nums[left] == target ? left : -1
}&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2025-05-19 오후 5.51.15.png&quot; data-origin-width=&quot;1378&quot; data-origin-height=&quot;906&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/o5NIG/btsN2MGPLXU/f7WbzkdbMdGkwYH2bjip7k/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/o5NIG/btsN2MGPLXU/f7WbzkdbMdGkwYH2bjip7k/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/o5NIG/btsN2MGPLXU/f7WbzkdbMdGkwYH2bjip7k/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fo5NIG%2FbtsN2MGPLXU%2Ff7WbzkdbMdGkwYH2bjip7k%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;500&quot; height=&quot;329&quot; data-filename=&quot;스크린샷 2025-05-19 오후 5.51.15.png&quot; data-origin-width=&quot;1378&quot; data-origin-height=&quot;906&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;</description>
      <category>&amp;rarr; Problems</category>
      <author>Swift librarian</author>
      <guid isPermaLink="true">https://swift-library.tistory.com/242</guid>
      <comments>https://swift-library.tistory.com/242#entry242comment</comments>
      <pubDate>Mon, 19 May 2025 18:02:54 +0900</pubDate>
    </item>
    <item>
      <title>[Algorithm] LeetCode - Maximum Product Subarray</title>
      <link>https://swift-library.tistory.com/240</link>
      <description>&lt;h2 data-ke-size=&quot;size26&quot;&gt;  문제&lt;/h2&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;a href=&quot;https://leetcode.com/problems/maximum-product-subarray/&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;Maximum Product Subarray&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;난이도 &lt;b&gt;&lt;span style=&quot;color: #f89009;&quot;&gt;Medium&lt;/span&gt;&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;부분배열중 가장 곱이 높은 배열을 찾는 문제&lt;/li&gt;
&lt;/ul&gt;
&lt;pre id=&quot;code_1747196192940&quot; class=&quot;swift&quot; data-ke-language=&quot;swift&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;Input: nums = [-2,0,-1]
Output: 0
Explanation: The result cannot be 2, because [-2,-1] is not a subarray.&lt;/code&gt;&lt;/pre&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;  풀이&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 문제의 고민은 만약에 부분합이라면 투포인터를 사용할 수 있지만 부분 곱셈에서는 조금 까다로운 문제가 있었다.&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;배열의 요소 중 하나라도 0이 나왔을 땐 무조건 곱이 0이 되므로 포인터를 움직이며 비교할 수 없다는 것.&lt;/li&gt;
&lt;li&gt;음수는 같은 음수를 만나면 오히려 더 높은 숫자가 나올 수 있다는 것.&lt;/li&gt;
&lt;/ol&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;결국 아래와 같이 maxBuffer, minBuffer를 두어 해결하고자 했다. 또한 0일 경우를 고려해서 아무것도 곱하지 않은 num부터도 가능하게 했다. 이렇게 푸니 O(n)의 시간복잡도로 풀 수 있었다.&lt;/p&gt;
&lt;pre id=&quot;code_1747196864348&quot; class=&quot;swift&quot; data-ke-language=&quot;swift&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;func maxProduct(_ nums: [Int]) -&amp;gt; Int {
    var result = nums[0]
    var maxBuffer = 1
    var minBuffer = 1

    for num in nums {
        let candidates = [num, maxBuffer * num, minBuffer * num]
        maxBuffer = candidates.max() ?? 1
        minBuffer = candidates.min() ?? 1
        result = max(result, maxBuffer)
    }

    return result
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;참고로 메모리부분은 이렇게 간단한 문제는 아래와 같이 똑같은 코드를 돌려도 그때그때 격차가 큰 것 같다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2025-05-14 오후 1.34.40.png&quot; data-origin-width=&quot;1234&quot; data-origin-height=&quot;896&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/qeQ8a/btsNX2H4i8U/6vNBD3GPbmZgQJ53xCYiJ1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/qeQ8a/btsNX2H4i8U/6vNBD3GPbmZgQJ53xCYiJ1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/qeQ8a/btsNX2H4i8U/6vNBD3GPbmZgQJ53xCYiJ1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FqeQ8a%2FbtsNX2H4i8U%2F6vNBD3GPbmZgQJ53xCYiJ1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;500&quot; height=&quot;363&quot; data-filename=&quot;스크린샷 2025-05-14 오후 1.34.40.png&quot; data-origin-width=&quot;1234&quot; data-origin-height=&quot;896&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2025-05-14 오후 1.35.30.png&quot; data-origin-width=&quot;1228&quot; data-origin-height=&quot;896&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/D2q64/btsNV32QQu7/p4HtPaVI8eepYL8DmHTJmk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/D2q64/btsNV32QQu7/p4HtPaVI8eepYL8DmHTJmk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/D2q64/btsNV32QQu7/p4HtPaVI8eepYL8DmHTJmk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FD2q64%2FbtsNV32QQu7%2Fp4HtPaVI8eepYL8DmHTJmk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;500&quot; height=&quot;365&quot; data-filename=&quot;스크린샷 2025-05-14 오후 1.35.30.png&quot; data-origin-width=&quot;1228&quot; data-origin-height=&quot;896&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;</description>
      <category>&amp;rarr; Problems</category>
      <author>Swift librarian</author>
      <guid isPermaLink="true">https://swift-library.tistory.com/240</guid>
      <comments>https://swift-library.tistory.com/240#entry240comment</comments>
      <pubDate>Wed, 14 May 2025 13:34:03 +0900</pubDate>
    </item>
    <item>
      <title>[Algorithm] LeetCode - Remove Nth Node From End of List</title>
      <link>https://swift-library.tistory.com/239</link>
      <description>&lt;h2 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size26&quot;&gt;  문제&lt;/h2&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;Remove Nth Node From End of List&lt;/li&gt;
&lt;li&gt;난이도:&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;span style=&quot;color: #f3c000;&quot;&gt;&lt;b&gt;Medium&lt;/b&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;연결리스트에서 끝에서 n번째의 요소를 제거하는 문제&lt;/li&gt;
&lt;/ul&gt;
&lt;pre id=&quot;code_1747054000418&quot; class=&quot;swift&quot; data-ke-language=&quot;swift&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;Input: head = [1,2,3,4,5], n = 2
Output: [1,2,3,5]&lt;/code&gt;&lt;/pre&gt;
&lt;h2 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size26&quot;&gt;  풀이&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;요즘 연결리스트 문제를 자주 푸는 것 같다. 이 문제는 먼저 n번 노드를 뒤로 보낸 후에 같이 이동하면서 next가 nil이면 &lt;b&gt;start.next = start.next.next&lt;/b&gt; 로 연결을 끊어주면 된다.&lt;/p&gt;
&lt;pre id=&quot;code_1747054032706&quot; class=&quot;swift&quot; data-ke-language=&quot;swift&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;func removeNthFromEnd(_ head: ListNode?, _ n: Int) -&amp;gt; ListNode? {
    let zero: ListNode? = ListNode(0)
    zero?.next = head

    var start = zero
    var end = zero

    for _ in 0..&amp;lt;n {
        end = end?.next
    }

    while let next = end?.next {
        start = start?.next
        end = next
    }

    start?.next = start?.next?.next

    return zero?.next
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Runtime에서 좋은 결과를 얻을 수 있었다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2025-05-12 오후 9.47.43.png&quot; data-origin-width=&quot;1376&quot; data-origin-height=&quot;902&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/muIcH/btsNUwJ95p6/GjCffWEfi1FIeIlxga666k/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/muIcH/btsNUwJ95p6/GjCffWEfi1FIeIlxga666k/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/muIcH/btsNUwJ95p6/GjCffWEfi1FIeIlxga666k/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FmuIcH%2FbtsNUwJ95p6%2FGjCffWEfi1FIeIlxga666k%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;500&quot; height=&quot;328&quot; data-filename=&quot;스크린샷 2025-05-12 오후 9.47.43.png&quot; data-origin-width=&quot;1376&quot; data-origin-height=&quot;902&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;</description>
      <category>&amp;rarr; Problems</category>
      <author>Swift librarian</author>
      <guid isPermaLink="true">https://swift-library.tistory.com/239</guid>
      <comments>https://swift-library.tistory.com/239#entry239comment</comments>
      <pubDate>Mon, 12 May 2025 21:49:06 +0900</pubDate>
    </item>
    <item>
      <title>[Algorithm] LeetCode - Reorder List</title>
      <link>https://swift-library.tistory.com/238</link>
      <description>&lt;h2 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size26&quot;&gt;  문제&lt;/h2&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;a href=&quot;https://leetcode.com/problems/reorder-list?envType=problem-list-v2&amp;amp;envId=oizxjoit&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;Reorder List&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;난이도: &lt;span style=&quot;color: #f89009;&quot;&gt;&lt;b&gt;Medium&lt;/b&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;주어진 리스트를 재배열하는 문제이다.&lt;/li&gt;
&lt;/ul&gt;
&lt;pre id=&quot;code_1747039868520&quot; class=&quot;swift&quot; data-ke-language=&quot;swift&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;You are given the head of a singly linked-list. The list can be represented as:

L0 &amp;rarr; L1 &amp;rarr; &amp;hellip; &amp;rarr; Ln - 1 &amp;rarr; Ln
Reorder the list to be on the following form:

L0 &amp;rarr; Ln &amp;rarr; L1 &amp;rarr; Ln - 1 &amp;rarr; L2 &amp;rarr; Ln - 2 &amp;rarr; &amp;hellip;
You may not modify the values in the list's nodes. Only nodes themselves may be changed.&lt;/code&gt;&lt;/pre&gt;
&lt;h2 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size26&quot;&gt;  풀이&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;아래와 같은 조건이 있었기 때문에 기존의 리스트를 가지고 재배열을 해야했다.&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style3&quot;&gt;You may not modify the values in the list's nodes. Only nodes themselves may be changed.&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;아래처럼 연결리스트를 반으로 잘라 뒤집어서 번갈아 넣으면 되지 않을까? 생각했다.&lt;/p&gt;
&lt;pre id=&quot;code_1747040387660&quot; class=&quot;swift&quot; data-ke-language=&quot;swift&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;1 -&amp;gt; 2 -&amp;gt; 3 -&amp;gt; 4 -&amp;gt; 5 -&amp;gt; 6 -&amp;gt; 7 -&amp;gt; 8

1 -&amp;gt; 2 -&amp;gt; 3 -&amp;gt; 4 | 5 &amp;lt;- 6 &amp;lt;- 7 &amp;lt;- 8&lt;/code&gt;&lt;/pre&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;1️⃣ 배열 중간 찾기&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;아래와 같이 한칸, 두칸을 가는 노드를 만들어서 중간지점을 찾았다. &lt;b&gt;O(n)&lt;/b&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1747040429944&quot; class=&quot;swift&quot; data-ke-language=&quot;swift&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;    var slow: ListNode? = head
    var fast: ListNode? = head

    while fast?.next != nil &amp;amp;&amp;amp; fast?.next?.next != nil {
        slow = slow?.next
        fast = fast?.next?.next
    }&lt;/code&gt;&lt;/pre&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;2️⃣ 중간부터 시작해서 배열 뒤집기&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;5 &amp;rarr; 6 &amp;rarr; 7 &amp;rarr; 8&lt;/b&gt; 리스트를 &lt;b&gt;5 &amp;larr; 6 &amp;larr; 7 &amp;larr; 8&lt;/b&gt; 로 만든다.&lt;/p&gt;
&lt;pre id=&quot;code_1747040512866&quot; class=&quot;swift&quot; data-ke-language=&quot;swift&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;    var postNode: ListNode? = nil
    var currentNode: ListNode? = slow?.next
    slow?.next = nil

    while let node = currentNode {
        let next = node.next
        node.next = postNode
        postNode = node
        currentNode = next
    }&lt;/code&gt;&lt;/pre&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;3️⃣ 리스트 번갈아가면서 연결하기&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;1부터 시작, 8부터 시작해서 번갈아가면서 연결한다.&lt;/p&gt;
&lt;pre id=&quot;code_1747040675218&quot; class=&quot;swift&quot; data-ke-language=&quot;swift&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;    var first: ListNode? = head
    var second: ListNode? = postNode

    while let node = second {
        let tmp1 = first?.next
        let tmp2 = node.next

        first?.next = second
        node.next = tmp1

        first = tmp1
        second = tmp2
    }&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;아래의 괜찮은 결과가 나왔다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2025-05-12 오후 6.07.25.png&quot; data-origin-width=&quot;1042&quot; data-origin-height=&quot;1004&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/MbmUh/btsNTmhj4dH/imBdZRnTYgtfwWoTrRsqVK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/MbmUh/btsNTmhj4dH/imBdZRnTYgtfwWoTrRsqVK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/MbmUh/btsNTmhj4dH/imBdZRnTYgtfwWoTrRsqVK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FMbmUh%2FbtsNTmhj4dH%2FimBdZRnTYgtfwWoTrRsqVK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;500&quot; height=&quot;482&quot; data-filename=&quot;스크린샷 2025-05-12 오후 6.07.25.png&quot; data-origin-width=&quot;1042&quot; data-origin-height=&quot;1004&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;pre id=&quot;code_1747041132749&quot; class=&quot;swift&quot; data-ke-language=&quot;swift&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;func reorderList(_ head: ListNode?) {
    guard let head = head, head.next != nil else { return }

    var slow: ListNode? = head
    var fast: ListNode? = head

    while fast?.next != nil &amp;amp;&amp;amp; fast?.next?.next != nil {
        slow = slow?.next
        fast = fast?.next?.next
    }

    var postNode: ListNode? = nil
    var currentNode: ListNode? = slow?.next
    slow?.next = nil

    while let node = currentNode {
        let next = node.next
        node.next = postNode
        postNode = node
        currentNode = next
    }

    var first: ListNode? = head
    var second: ListNode? = postNode

    while let node = second {
        let tmp1 = first?.next
        let tmp2 = node.next

        first?.next = second
        node.next = tmp1

        first = tmp1
        second = tmp2
    }
}&lt;/code&gt;&lt;/pre&gt;</description>
      <category>&amp;rarr; Problems</category>
      <author>Swift librarian</author>
      <guid isPermaLink="true">https://swift-library.tistory.com/238</guid>
      <comments>https://swift-library.tistory.com/238#entry238comment</comments>
      <pubDate>Mon, 12 May 2025 18:11:52 +0900</pubDate>
    </item>
    <item>
      <title>[Algorithm] LeetCode - 3Sum</title>
      <link>https://swift-library.tistory.com/237</link>
      <description>&lt;h2 data-ke-size=&quot;size26&quot;&gt;  문제&lt;/h2&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;a href=&quot;https://leetcode.com/problems/3sum?envType=problem-list-v2&amp;amp;envId=oizxjoit&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;3Sum&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;난이도: &lt;span style=&quot;color: #f3c000;&quot;&gt;&lt;b&gt;Medium&lt;/b&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;배열중 3개를 뽑아 더하면 0이 되는 배열을 겹치지 않게 뽑는 문제&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class=&quot;swift&quot; data-ke-language=&quot;swift&quot;&gt;&lt;code&gt;Input: nums = [-1,0,1,2,-1,-4]
Output: [[-1,-1,2],[-1,0,1]]
Explanation: 
nums[0] + nums[1] + nums[2] = (-1) + 0 + 1 = 0.
nums[1] + nums[2] + nums[4] = 0 + 1 + (-1) = 0.
nums[0] + nums[3] + nums[4] = (-1) + 2 + (-1) = 0.
The distinct triplets are [-1,0,1] and [-1,-1,2].
Notice that the order of the output and the order of the triplets does not matter.&lt;/code&gt;&lt;/pre&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;  Brute Force&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;항상 문제를 보면 단순하게 한번 풀어본다. 아래의 풀이는 단순하게 &lt;b&gt;O(n^3)&lt;/b&gt;으로 푸는 방법인데 당연하게도 시간초과가 난다. &lt;span style=&quot;color: #666666;&quot;&gt;(nums.length는 최대&amp;nbsp;3,000이라 단순 연산으로 최대 27,000,000,000번 연산을 하게 될 수 있으니까... )&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1746968624576&quot; class=&quot;swift&quot; data-ke-language=&quot;swift&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;func threeSum(_ nums: [Int]) -&amp;gt; [[Int]] {
    let nums = nums.sorted()
    var triplets: [[Int]] = []

    for i in 0..&amp;lt;nums.count {
        for j in i+1..&amp;lt;nums.count {
            for k in j+1..&amp;lt;nums.count {
                let triplet = [nums[i], nums[j], nums[k]]
                if triplet.reduce(0, +) == 0 &amp;amp;&amp;amp; !triplets.contains(triplet) {
                    triplets.append(triplet)
                }
            }
        }
    }

    return triplets
}&lt;/code&gt;&lt;/pre&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;  풀이&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이문제는 좌표 하나를 기반으로 정렬을 한 후 투포인터 알고리즘을 쓰면 된다. 이렇게 된다면 &lt;b&gt;O(n^2)&lt;/b&gt;이다. 살짝 까다로운것이 배열이 중복되면 안되기 때문에 똑같은 숫자로 시작하거나 0이 나왔을 때도 똑같은 숫자를 소거해줘야 한다.&lt;/p&gt;
&lt;pre class=&quot;swift&quot; data-ke-language=&quot;swift&quot;&gt;&lt;code&gt;func threeSum(_ nums: [Int]) -&amp;gt; [[Int]] {
    let nums = nums.sorted()
    var triplets: [[Int]] = []

    for i in nums.indices {
        /// 똑같은 숫자면 투포인터를 하지 않는다.
        if i &amp;gt; 0 &amp;amp;&amp;amp; nums[i] == nums[i-1] { continue }

        var left = i + 1
        var right = nums.count - 1

        while left &amp;lt; right {
            let sum = nums[i] + nums[left] + nums[right]

            if sum == 0 {
                triplets.append([nums[i], nums[left], nums[right]])
               
                /// 0이 나오면 똑같은 숫자를 건너뛴다.
                while left &amp;lt; right &amp;amp;&amp;amp; nums[left] == nums[left + 1] { left += 1 }
                while left &amp;lt; right &amp;amp;&amp;amp; nums[right] == nums[right - 1] { right -= 1 }

                left += 1
                right -= 1
            } else if sum &amp;lt; 0 {
                left += 1
            } else {
                right -= 1
            }
        }
    }

    return triplets
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;결과는 아래와 같이 준수한(?) 결과가 나왔다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2025-05-11 오후 10.44.23.png&quot; data-origin-width=&quot;1354&quot; data-origin-height=&quot;894&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/6EZv7/btsNS9Vl36S/551msfb6wUh0bYTk9kfKP0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/6EZv7/btsNS9Vl36S/551msfb6wUh0bYTk9kfKP0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/6EZv7/btsNS9Vl36S/551msfb6wUh0bYTk9kfKP0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F6EZv7%2FbtsNS9Vl36S%2F551msfb6wUh0bYTk9kfKP0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;500&quot; height=&quot;330&quot; data-filename=&quot;스크린샷 2025-05-11 오후 10.44.23.png&quot; data-origin-width=&quot;1354&quot; data-origin-height=&quot;894&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;br /&gt;&lt;br /&gt;&lt;/p&gt;</description>
      <category>&amp;rarr; Problems</category>
      <author>Swift librarian</author>
      <guid isPermaLink="true">https://swift-library.tistory.com/237</guid>
      <comments>https://swift-library.tistory.com/237#entry237comment</comments>
      <pubDate>Sun, 11 May 2025 22:43:46 +0900</pubDate>
    </item>
    <item>
      <title>[Algorithm] LeetCode - Missing Number</title>
      <link>https://swift-library.tistory.com/236</link>
      <description>&lt;h2 data-ke-size=&quot;size26&quot;&gt;  문제&lt;/h2&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;a href=&quot;https://leetcode.com/problems/missing-number?envType=problem-list-v2&amp;amp;envId=oizxjoit&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;Missing Number&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;난이도: &lt;b&gt;&lt;span style=&quot;color: #f89009;&quot;&gt;Easy&lt;/span&gt;&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;주어진 0부터 n까지 있는 배열에서 비어있는 숫자를 찾는 문제&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class=&quot;swift&quot; data-ke-language=&quot;swift&quot;&gt;&lt;code&gt;Input: nums = [3,0,1]
Output: 2
Explanation: n = 3 since there are 3 numbers, so all numbers are in the range [0,3]. 2 is the missing number in the range since it does not appear in nums.&lt;/code&gt;&lt;/pre&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;  풀이&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 문제는 아주 단순하게 풀린다. 모든 수를 더하고 배열을 순회하면서 마이너스하면 결국 없는 숫자가 남게 된다. 한줄로 해결도 가능하다!  &lt;/p&gt;
&lt;pre id=&quot;code_1746963591189&quot; class=&quot;swift&quot; data-ke-language=&quot;swift&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;func missingNumber(_ nums: [Int]) -&amp;gt; Int {
    nums.reduce((nums.count * (nums.count + 1) / 2), -)
}&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2025-05-11 오후 8.51.39.png&quot; data-origin-width=&quot;1192&quot; data-origin-height=&quot;1116&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/K7rQJ/btsNSBZfdst/bgpsZGJWSJOKMeQPXGnHik/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/K7rQJ/btsNSBZfdst/bgpsZGJWSJOKMeQPXGnHik/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/K7rQJ/btsNSBZfdst/bgpsZGJWSJOKMeQPXGnHik/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FK7rQJ%2FbtsNSBZfdst%2FbgpsZGJWSJOKMeQPXGnHik%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;500&quot; height=&quot;468&quot; data-filename=&quot;스크린샷 2025-05-11 오후 8.51.39.png&quot; data-origin-width=&quot;1192&quot; data-origin-height=&quot;1116&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>&amp;rarr; Problems</category>
      <author>Swift librarian</author>
      <guid isPermaLink="true">https://swift-library.tistory.com/236</guid>
      <comments>https://swift-library.tistory.com/236#entry236comment</comments>
      <pubDate>Sun, 11 May 2025 20:53:55 +0900</pubDate>
    </item>
    <item>
      <title>[Algorithm] LeetCode - Linked List Cycle</title>
      <link>https://swift-library.tistory.com/235</link>
      <description>&lt;h2 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size26&quot;&gt;  문제&lt;/h2&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;Linked List Cycle&lt;/li&gt;
&lt;li&gt;난이도:&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;span style=&quot;color: #009a87;&quot;&gt;Easy&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;연결리스트 사이클이 있는지 찾는 문제&lt;/li&gt;
&lt;/ul&gt;
&lt;pre id=&quot;code_1746772481870&quot; class=&quot;swift&quot; data-ke-language=&quot;swift&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;Input: head = [3,2,0,-4], pos = 1
Output: true
Explanation: There is a cycle in the linked list, where the tail connects to the 1st node (0-indexed).&lt;/code&gt;&lt;/pre&gt;
&lt;h2 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size26&quot;&gt;  풀이&lt;/h2&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;솔직히 이 문제가 왜 &lt;span style=&quot;color: #009a87;&quot;&gt;Easy&lt;/span&gt;인지 모르겠다. 아래처럼 ListNode 배열이나 ObjectIdentifier 집합을 사용하여 풀면 풀리긴 하지만... 이런 문제를 풀 때 아주아주 유명한 알고리즘이 있다.&lt;/p&gt;
&lt;pre id=&quot;code_1746774241801&quot; class=&quot;swift&quot; data-ke-language=&quot;swift&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;func hasCycle(_ head: ListNode?) -&amp;gt; Bool {
    var visited: [ListNode] = []
    var current = head

    while let node = current {
        if visited.contains(where: { $0 === node }) { return true }
        visited.append(node)
        current = node.next
    }

    return false
}

func hasCycle(_ head: ListNode?) -&amp;gt; Bool {
    var visited = Set&amp;lt;ObjectIdentifier&amp;gt;()
    var current = head

    while let node = current {
        let id = ObjectIdentifier(node)
        if visited.contains(id) {
            return true
        }
        visited.insert(id)
        current = node.next
    }

    return false
}&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2025-05-09 오후 3.39.36.png&quot; data-origin-width=&quot;1162&quot; data-origin-height=&quot;1122&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/oLgCM/btsNRebJuP4/yOh7pL6OQPzrVmxMsfAex1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/oLgCM/btsNRebJuP4/yOh7pL6OQPzrVmxMsfAex1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/oLgCM/btsNRebJuP4/yOh7pL6OQPzrVmxMsfAex1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FoLgCM%2FbtsNRebJuP4%2FyOh7pL6OQPzrVmxMsfAex1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;500&quot; height=&quot;483&quot; data-filename=&quot;스크린샷 2025-05-09 오후 3.39.36.png&quot; data-origin-width=&quot;1162&quot; data-origin-height=&quot;1122&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;바로 아래처럼 &lt;b&gt;플로이드의 토끼와 거북이 알고리즘&lt;/b&gt;을 사용하면 저장하는것이 없기 때문에 훨씬 효율적으로 풀 수 있다. 거북이는 한 칸 이동, 토끼는 두 칸 이동! 사이클의 개수는 홀수 혹은 짝수이기 때문에 언젠간 만난다.&lt;/p&gt;
&lt;pre id=&quot;code_1746772587345&quot; class=&quot;swift&quot; data-ke-language=&quot;swift&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;func hasCycle(_ head: ListNode?) -&amp;gt; Bool {
    var   = head
    var   = head

    while let next =  ?.next?.next {
          =  ?.next
          = next

        if   ===   { return true }
    }

    return false
}&lt;/code&gt;&lt;/pre&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2025-05-09 오후 3.37.36.png&quot; data-origin-width=&quot;1166&quot; data-origin-height=&quot;1118&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/MzLHs/btsNSxnM3wD/4qquDNXRc86tKD3DpNwyJ1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/MzLHs/btsNSxnM3wD/4qquDNXRc86tKD3DpNwyJ1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/MzLHs/btsNSxnM3wD/4qquDNXRc86tKD3DpNwyJ1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FMzLHs%2FbtsNSxnM3wD%2F4qquDNXRc86tKD3DpNwyJ1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;500&quot; height=&quot;479&quot; data-filename=&quot;스크린샷 2025-05-09 오후 3.37.36.png&quot; data-origin-width=&quot;1166&quot; data-origin-height=&quot;1118&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;아래와 같이 문제와 관련된 유튜버 &lt;b&gt;Joma Tech&lt;/b&gt;님의 재미있는 영상도 있다.&lt;/p&gt;
&lt;figure data-ke-type=&quot;video&quot; data-ke-style=&quot;alignCenter&quot; data-video-host=&quot;youtube&quot; data-video-url=&quot;https://www.youtube.com/watch?v=pKO9UjSeLew&quot; data-video-thumbnail=&quot;https://scrap.kakaocdn.net/dn/bzV0tf/hyYRjTlAPJ/YRaweznKNyd2ZMCC47Oht0/img.jpg?width=1280&amp;amp;height=720&amp;amp;face=702_276_978_576,https://scrap.kakaocdn.net/dn/b4c54c/hyYRv0zgCG/jzeikvg9F0MvPWanXM72sK/img.jpg?width=1280&amp;amp;height=720&amp;amp;face=702_276_978_576&quot; data-video-width=&quot;700&quot; data-video-height=&quot;394&quot; data-video-origin-width=&quot;860&quot; data-video-origin-height=&quot;484&quot; data-ke-mobilestyle=&quot;widthContent&quot; data-video-title=&quot;If Programming Was An Anime&quot; data-original-url=&quot;&quot;&gt;&lt;iframe src=&quot;https://www.youtube.com/embed/pKO9UjSeLew&quot; width=&quot;700&quot; height=&quot;394&quot; frameborder=&quot;&quot; allowfullscreen=&quot;true&quot;&gt;&lt;/iframe&gt;
&lt;figcaption style=&quot;display: none;&quot;&gt;&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&gt;</description>
      <category>&amp;rarr; Problems</category>
      <author>Swift librarian</author>
      <guid isPermaLink="true">https://swift-library.tistory.com/235</guid>
      <comments>https://swift-library.tistory.com/235#entry235comment</comments>
      <pubDate>Fri, 9 May 2025 16:07:42 +0900</pubDate>
    </item>
    <item>
      <title>[Algorithm] LeetCode - Word Break</title>
      <link>https://swift-library.tistory.com/234</link>
      <description>&lt;h2 data-ke-size=&quot;size26&quot;&gt;  문제&lt;/h2&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;a href=&quot;https://leetcode.com/problems/word-break?envType=problem-list-v2&amp;amp;envId=oizxjoit&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;Word Break&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;난이도: &lt;span style=&quot;color: #f89009;&quot;&gt;Medium&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;단어 사전에 있는 단어 조합으로 주어진 문자열을 모두 대체할 수 있는지 찾는 문제&lt;/li&gt;
&lt;/ul&gt;
&lt;pre id=&quot;code_1746769265433&quot; class=&quot;swift&quot; data-ke-language=&quot;swift&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;Input: s = &quot;leetcode&quot;, wordDict = [&quot;leet&quot;,&quot;code&quot;]
Output: true
Explanation: Return true because &quot;leetcode&quot; can be segmented as &quot;leet code&quot;.&lt;/code&gt;&lt;/pre&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;  시행착오&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;아래와 같이 풀면 되지 않을까? 생각했다. 앞에서부터 순회하지 않는 이유는 word, words 같은 두 개의 문자가 있을 때 words를 대체해야 하기 때문에 앞에서부터 하면 word를 하고 s가 남지 않을까? 해서였다.&lt;/p&gt;
&lt;pre id=&quot;code_1746769305074&quot; class=&quot;swift&quot; data-ke-language=&quot;swift&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;func wordBreak(_ s: String, _ wordDict: [String]) -&amp;gt; Bool {
    var words = Set(wordDict)
    var buffer = &quot;&quot;

    for chr in s.reversed() {
        buffer = String(chr) + buffer

        if words.contains(buffer) {
            buffer = &quot;&quot;
        }
    }

    return buffer.isEmpty
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;하지만 이 풀이는 &lt;b&gt;s = &quot;aaaaaaa&quot; wordDick = [&quot;aaa&quot;, &quot;aaaa&quot;]&lt;/b&gt; 일때 바로 실패했다. ☠️ 왜냐하면 결국 a가 남기 때문에...!&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2025-05-09 오후 2.57.43.png&quot; data-origin-width=&quot;1214&quot; data-origin-height=&quot;796&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bjScDT/btsNRPCETzj/2dOYgyF813hRH4atK9o3k1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bjScDT/btsNRPCETzj/2dOYgyF813hRH4atK9o3k1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bjScDT/btsNRPCETzj/2dOYgyF813hRH4atK9o3k1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbjScDT%2FbtsNRPCETzj%2F2dOYgyF813hRH4atK9o3k1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;500&quot; height=&quot;328&quot; data-filename=&quot;스크린샷 2025-05-09 오후 2.57.43.png&quot; data-origin-width=&quot;1214&quot; data-origin-height=&quot;796&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;h2 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size26&quot;&gt;  풀이&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;결국 이 문제는 dp로 풀게 되었다. 이전의 검증된 배열에서 추가로 단어를 더해가는 것이기 때문에 아래와 같이 dp배열을 만들어 준 뒤, 해당 길이까지 &lt;b&gt;true&lt;/b&gt;라면 그때 이후로 단어가 들어가 있는지를 확인하는 방식이다.&lt;/p&gt;
&lt;pre id=&quot;code_1746769669121&quot; class=&quot;swift&quot; data-ke-language=&quot;swift&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;func wordBreak(_ s: String, _ wordDict: [String]) -&amp;gt; Bool {
    var words = Set(wordDict)
    var chrs = Array(s)
    
    var dp = Array(repeating: false, count: s.count + 1)
    dp[0] = true

    for i in 1...s.count {
        for j in 0..&amp;lt;i {
            let word = String(chrs[j..&amp;lt;i])

            if dp[j] &amp;amp;&amp;amp; words.contains(word) {
                dp[i] = true
                break
            }
        }
    }

    return dp[s.count]
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;살짝 아쉬운 결과가 나왔다. 뭔가 놓친 게 있는 걸까?&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2025-05-09 오후 2.50.10.png&quot; data-origin-width=&quot;1390&quot; data-origin-height=&quot;896&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/m9wOi/btsNQYz5bf2/uvurHIqfeHjB1lf9dWEUw0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/m9wOi/btsNQYz5bf2/uvurHIqfeHjB1lf9dWEUw0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/m9wOi/btsNQYz5bf2/uvurHIqfeHjB1lf9dWEUw0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fm9wOi%2FbtsNQYz5bf2%2FuvurHIqfeHjB1lf9dWEUw0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;500&quot; height=&quot;322&quot; data-filename=&quot;스크린샷 2025-05-09 오후 2.50.10.png&quot; data-origin-width=&quot;1390&quot; data-origin-height=&quot;896&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;  개선된 풀이&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;모든 단어의 개수보다는 사전에 있는 단어 개수로만 판단하면 되지 않을까라는 생각에 아래와 같이 wordCounts배열을 만든 뒤 이 안에 있는 값만 활용했다. 물론 &lt;b&gt;longestWordCount&lt;/b&gt;만 찾아서 판별하는 방법도 있긴 하지만 아래의 방식이 좀 더 이해가 되는 느낌이 들어 아래와 같이 작성했다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;물론 여기서 &lt;b&gt;sorted(by: &amp;gt;)&lt;/b&gt;로 긴 단어부터 체크하면 시간이 조금 더 빨라졌지만 그건 테스트케이스에 따라 그리고 LeetCode는 빌드할 때마다 근소한 차이가 보이기 때문에 큰 의미가 없다고 생각했다. 오히려 &lt;b&gt;sorted&lt;/b&gt;를 해주면 &lt;b&gt;O(n)&lt;/b&gt;이 &lt;b&gt;O(nlogn)&lt;/b&gt;으로 늘어나기 때문에 좋지 않다고 판단했다.&lt;/p&gt;
&lt;pre id=&quot;code_1746769919857&quot; class=&quot;swift&quot; data-ke-language=&quot;swift&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;func wordBreak(_ s: String, _ wordDict: [String]) -&amp;gt; Bool {
    var words = Set(wordDict)
    var wordCounts = words.map { $0.count }
    var chrs = Array(s)
    
    var dp = Array(repeating: false, count: s.count + 1)
    dp[0] = true

    for end in 1...s.count {
        for wordCount in wordCounts {
            let start = max(end - wordCount, 0)

            let word = String(chrs[start..&amp;lt;end])

            if dp[start] &amp;amp;&amp;amp; words.contains(word) {
                dp[end] = true
                break
            }
        }
    }

    return dp[s.count]
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;9ms로 만족할 만한 결과가 나왔다. 돌릴 때마다&amp;nbsp;&lt;b&gt;2~3ms&lt;/b&gt;는 편차가 있는 듯하다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2025-05-09 오후 2.53.43.png&quot; data-origin-width=&quot;1228&quot; data-origin-height=&quot;892&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/lLbhJ/btsNSdbWFGR/bgdZuQaTHFm5z9BIxtY4R1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/lLbhJ/btsNSdbWFGR/bgdZuQaTHFm5z9BIxtY4R1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/lLbhJ/btsNSdbWFGR/bgdZuQaTHFm5z9BIxtY4R1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FlLbhJ%2FbtsNSdbWFGR%2FbgdZuQaTHFm5z9BIxtY4R1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;500&quot; height=&quot;363&quot; data-filename=&quot;스크린샷 2025-05-09 오후 2.53.43.png&quot; data-origin-width=&quot;1228&quot; data-origin-height=&quot;892&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;</description>
      <category>&amp;rarr; Problems</category>
      <author>Swift librarian</author>
      <guid isPermaLink="true">https://swift-library.tistory.com/234</guid>
      <comments>https://swift-library.tistory.com/234#entry234comment</comments>
      <pubDate>Fri, 9 May 2025 14:58:15 +0900</pubDate>
    </item>
    <item>
      <title>[Algorithm] LeetCode - Container With Most Water</title>
      <link>https://swift-library.tistory.com/233</link>
      <description>&lt;h2 data-ke-size=&quot;size26&quot;&gt;  문제&lt;/h2&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;a href=&quot;https://leetcode.com/problems/container-with-most-water?envType=problem-list-v2&amp;amp;envId=oizxjoit&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;Container With Most Water&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;난이도: &lt;b&gt;&lt;span style=&quot;color: #f89009;&quot;&gt;Medium&lt;/span&gt;&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;주어진 배열에서 양 끝점으로 한 가장 큰 직사각형의 넓이를 구하는 문제&lt;/li&gt;
&lt;/ul&gt;
&lt;pre id=&quot;code_1746695242183&quot; class=&quot;swift&quot; data-ke-language=&quot;swift&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;Input: height = [1,8,6,2,5,4,8,3,7]
Output: 49
Explanation: The above vertical lines are represented by array [1,8,6,2,5,4,8,3,7]. In this case, the max area of water (blue section) the container can contain is 49.&lt;/code&gt;&lt;/pre&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;  풀이&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;첫 번째로 가장 무식하게 모든 경우의 수를 체크하는 방법이 있다. 물론 n의 입력값이 10^5이기 때문에 시간초과!&lt;/p&gt;
&lt;pre id=&quot;code_1746695366585&quot; class=&quot;swift&quot; data-ke-language=&quot;swift&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;func maxArea(_ height: [Int]) -&amp;gt; Int {
    let count = height.count
    var result = 0
    
    for start in 0..&amp;lt;count {
        for end in (start..&amp;lt;count) {
            let area = (end - start) * min(height[start], height[end])
            result = max(result, area)
        }
    }

    return result
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;어떻게 효율적으로 접근할 수 있을까?   이 문제가 정말 재밌었던 게 조금만 생각해 보면 쉬운 방법이 나온다. 조건 하나만 추가해 주면 문제가 풀린다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2025-05-08 오후 6.25.11.png&quot; data-origin-width=&quot;1236&quot; data-origin-height=&quot;898&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/PoPYW/btsNP6EsQ44/BKYKu4iMMTLhrJKmNGB0Wk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/PoPYW/btsNP6EsQ44/BKYKu4iMMTLhrJKmNGB0Wk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/PoPYW/btsNP6EsQ44/BKYKu4iMMTLhrJKmNGB0Wk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FPoPYW%2FbtsNP6EsQ44%2FBKYKu4iMMTLhrJKmNGB0Wk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;500&quot; height=&quot;363&quot; data-filename=&quot;스크린샷 2025-05-08 오후 6.25.11.png&quot; data-origin-width=&quot;1236&quot; data-origin-height=&quot;898&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;바로바로 아래의 조건 한줄을 루프에 추가해 주면 된다. 그 이유는 만약에 양끝에서 시작해서&amp;nbsp;&lt;b&gt;height[start]&lt;/b&gt;가 &lt;b&gt;height[end]&lt;/b&gt;보다 적다면 종료해 주면 된다. 그때가 바로 최대일 수밖에 없다. &lt;b&gt;start&lt;/b&gt;의 높이는 고정이 되어있기 때문에 &lt;b&gt;height[start]&lt;/b&gt;의 높이를 사용해서 넓이를 쟀을 때가 최대이다.&lt;/p&gt;
&lt;pre id=&quot;code_1746696339672&quot; class=&quot;swift&quot; data-ke-language=&quot;swift&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;if height[start] &amp;lt; height[end] { break }&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;최종 코드는 아래와 같다.&lt;/p&gt;
&lt;pre id=&quot;code_1746696164689&quot; class=&quot;swift&quot; data-ke-language=&quot;swift&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;func maxArea(_ height: [Int]) -&amp;gt; Int {
    let count = height.count
    var result = 0
    
    for start in 0..&amp;lt;count {
        for end in (start..&amp;lt;count).reversed() {
            let area = (end - start) * min(height[start], height[end])
            result = max(result, area)
            if height[start] &amp;lt; height[end] { break }
        }
    }

    return result
}&lt;/code&gt;&lt;/pre&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;  풀이 개선&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;하지만 아쉬웠던 건 &lt;b&gt;92ms&lt;/b&gt;로 풀긴 했지만 &lt;b&gt;Beats 5.19%&lt;/b&gt;... 그리고 위의 풀이는 결국 O(n^2)의 시간복잡도이다. 결국 이것보다 훨씬 효율적인 방법이 있다는 뜻이다. 바로바로 투포인터 알고리즘! &lt;b&gt;left&lt;/b&gt;, &lt;b&gt;right&lt;/b&gt;부터 시작해서 높이가 더 높은곳으로 나아가는 방식으로 코드를 작성하면 &lt;b&gt;O(n)&lt;/b&gt;의 시간복잡도로 풀 수 있다.&lt;/p&gt;
&lt;pre id=&quot;code_1746697199483&quot; class=&quot;swift&quot; data-ke-language=&quot;swift&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;func maxArea(_ height: [Int]) -&amp;gt; Int {
    var left = 0
    var right = height.count - 1
    var result = 0

    while left &amp;lt; right {
        let area = (right - left) * min(height[left], height[right])
        result = max(result, area)

        if height[left] &amp;lt; height[right] {
            left += 1
        } else {
            right -= 1
        }
    }

    return result
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;오케이... 3ms로 약 30배 빠르게 개선했다. 하지만 내앞에 계신 60%분들도 제치고 싶다...!&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2025-05-08 오후 6.43.44.png&quot; data-origin-width=&quot;1232&quot; data-origin-height=&quot;892&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/0I3vZ/btsNQwJCv8b/uZKFVKt4EKsquzxFocPkpK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/0I3vZ/btsNQwJCv8b/uZKFVKt4EKsquzxFocPkpK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/0I3vZ/btsNQwJCv8b/uZKFVKt4EKsquzxFocPkpK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F0I3vZ%2FbtsNQwJCv8b%2FuZKFVKt4EKsquzxFocPkpK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;500&quot; height=&quot;362&quot; data-filename=&quot;스크린샷 2025-05-08 오후 6.43.44.png&quot; data-origin-width=&quot;1232&quot; data-origin-height=&quot;892&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;O(n)&lt;/b&gt;보다 개선하는 것은 조건을 추가해주지 않는 이상 불가능하다. 우선 불필요한 연산을 줄이고자 &lt;b&gt;max&lt;/b&gt;함수를 쓰지 않고 아래와 같이 코드를 작성했더니 바로 개선이 되었다.&lt;/p&gt;
&lt;pre id=&quot;code_1746697781126&quot; class=&quot;swift&quot; data-ke-language=&quot;swift&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;func maxArea(_ height: [Int]) -&amp;gt; Int {
    var left = 0
    var right = height.count - 1
    var result = 0

    while left &amp;lt; right {
        let area = (right - left) * min(height[left], height[right])
        if area &amp;gt; result { result = area } // max 함수를 쓰지 않음

        if height[left] &amp;lt; height[right] {
            left += 1
        } else {
            right -= 1
        }
    }

    return result
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;0ms&lt;/b&gt;... 굳...  계산상 ♾️배 개선했다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2025-05-08 오후 6.56.25.png&quot; data-origin-width=&quot;1238&quot; data-origin-height=&quot;898&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/rmTyg/btsNN4Bf8ts/nfYHkH6sLzmHSMpbpTgMD1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/rmTyg/btsNN4Bf8ts/nfYHkH6sLzmHSMpbpTgMD1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/rmTyg/btsNN4Bf8ts/nfYHkH6sLzmHSMpbpTgMD1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FrmTyg%2FbtsNN4Bf8ts%2FnfYHkH6sLzmHSMpbpTgMD1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;500&quot; height=&quot;363&quot; data-filename=&quot;스크린샷 2025-05-08 오후 6.56.25.png&quot; data-origin-width=&quot;1238&quot; data-origin-height=&quot;898&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;</description>
      <category>&amp;rarr; Problems</category>
      <author>Swift librarian</author>
      <guid isPermaLink="true">https://swift-library.tistory.com/233</guid>
      <comments>https://swift-library.tistory.com/233#entry233comment</comments>
      <pubDate>Thu, 8 May 2025 18:32:55 +0900</pubDate>
    </item>
    <item>
      <title>[Algorithm] LeetCode - Clone Graph</title>
      <link>https://swift-library.tistory.com/232</link>
      <description>&lt;h2 data-ke-size=&quot;size26&quot;&gt;  문제&lt;/h2&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;a href=&quot;https://leetcode.com/problems/clone-graph?envType=problem-list-v2&amp;amp;envId=oizxjoit&quot;&gt;Clone&amp;nbsp;Graph&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;난이도: &lt;span style=&quot;color: #f89009;&quot;&gt;Medium&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;주어진 그래프를 &lt;b&gt;깊은 복사&lt;/b&gt;하는 문제이다.&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class=&quot;bash&quot; data-ke-language=&quot;bash&quot;&gt;&lt;code&gt;class Node {
    public int val;
    public List&amp;lt;Node&amp;gt; neighbors;
}

Input: adjList = [[2,4],[1,3],[2,4],[1,3]]
Output: [[2,4],[1,3],[2,4],[1,3]]&lt;/code&gt;&lt;/pre&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;  풀이&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;어어...? 이 문제를 풀면서 살짝 당황했다. 당연히 쉽게 생각했던 깊은 복사가 생각보다 쉽지 않구나라는 것을 알게 되었다. 왜냐하면 새로운 객체를 생성하면서 연결된 객체들을 다시 연결해줘야 하기 때문에 이것이 생각보다 까다롭다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;문제에서 가지고 있는 &lt;b&gt;val&lt;/b&gt;을 &lt;b&gt;key&lt;/b&gt;로 사용하고 새롭게 인스턴스를 만들면 된다. 만약 &lt;b&gt;val&lt;/b&gt;이 없다면 &lt;b&gt;Swift&lt;/b&gt;는 &lt;b&gt;ObjectIdentifier&lt;/b&gt;를 활용하면 된다. 나는 &lt;b&gt;mapped&lt;/b&gt;라는 딕셔너리를 활용하여 객체에 바로 접근하고 그 객체에 연결된 객체를 새로운 객체를 만들어서 연결해주었다. 연결된 객체를 방문하는 방식은 BFS를 사용했다.&lt;/p&gt;
&lt;pre id=&quot;code_1746591161502&quot; class=&quot;swift&quot; data-ke-language=&quot;swift&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;class Solution {
    func cloneGraph(_ node: Node?) -&amp;gt; Node? {
        guard let node else { return nil }
        
        let copied = Node(node.val)
        var mapped: [Int: Node] = [node.val: copied]

        var queue = [node]
        var i = 0

        while queue.count &amp;gt; i {
            let popped = queue[i]
            let neighbors = popped.neighbors.compactMap { $0 }

            neighbors.forEach { node in
                let value = node.val
                
                if mapped[value] == nil {
                    mapped[value] = Node(value)
                    queue.append(node)
                }

                mapped[popped.val]?.neighbors.append(mapped[value])
            }

            i += 1
        }

        return copied
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;결과는 아래와 같았다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2025-05-07 오후 1.21.27.png&quot; data-origin-width=&quot;1342&quot; data-origin-height=&quot;898&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/biKk40/btsNMBdvywG/5u7d6bKG04fk3NHpjseKKk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/biKk40/btsNMBdvywG/5u7d6bKG04fk3NHpjseKKk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/biKk40/btsNMBdvywG/5u7d6bKG04fk3NHpjseKKk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbiKk40%2FbtsNMBdvywG%2F5u7d6bKG04fk3NHpjseKKk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;600&quot; height=&quot;401&quot; data-filename=&quot;스크린샷 2025-05-07 오후 1.21.27.png&quot; data-origin-width=&quot;1342&quot; data-origin-height=&quot;898&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;</description>
      <category>&amp;rarr; Problems</category>
      <author>Swift librarian</author>
      <guid isPermaLink="true">https://swift-library.tistory.com/232</guid>
      <comments>https://swift-library.tistory.com/232#entry232comment</comments>
      <pubDate>Wed, 7 May 2025 13:23:25 +0900</pubDate>
    </item>
  </channel>
</rss>