{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# 연결 리스트"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 팰린드롬 연결 리스트"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "https://leetcode.com/problems/palindrome-linked-list/"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "연결 리스트가 팰린드롬 구조인지 판별하라\n",
    "\n",
    "입력 : \n",
    "\n",
    "1->2\n",
    "\n",
    "출력 :\n",
    "\n",
    "false\n",
    "\n",
    "입력 :\n",
    "\n",
    "1->2->2->1\n",
    "\n",
    "출력 : \n",
    "\n",
    "true"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {},
   "outputs": [],
   "source": [
    "class ListNode:\n",
    "    def __init__(self, val=0, next=None):\n",
    "        self.val = val\n",
    "        self.next = next        "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "metadata": {},
   "outputs": [],
   "source": [
    "node_2 = ListNode(2)\n",
    "node_1 = ListNode(1, node_2)\n",
    "\n",
    "node_6 = ListNode(1)\n",
    "node_5 = ListNode(2, node_6)\n",
    "node_4 = ListNode(2, node_5)\n",
    "node_3 = ListNode(1, node_4)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 34,
   "metadata": {},
   "outputs": [],
   "source": [
    "def isPalindrome(head: ListNode) -> bool:\n",
    "    checker = []\n",
    "\n",
    "    cur = head\n",
    "    while cur:\n",
    "        checker.append(cur.val)\n",
    "        cur = cur.next\n",
    "    \n",
    "    return checker == checker[::-1]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 35,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "False"
      ]
     },
     "execution_count": 35,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "isPalindrome(node_1)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 31,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[1]\n",
      "[1, 2]\n",
      "[1, 2, 2]\n",
      "[1, 2, 2, 1]\n"
     ]
    },
    {
     "data": {
      "text/plain": [
       "True"
      ]
     },
     "execution_count": 31,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "isPalindrome(node_3)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "\tAccepted\t64 ms\t24.5 MB\tpython3"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 풀이 1. 리스트 변환"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 36,
   "metadata": {},
   "outputs": [],
   "source": [
    "def isPalindrome(head: ListNode) -> bool:\n",
    "    q = []\n",
    "    \n",
    "    if not head:\n",
    "        return True\n",
    "    \n",
    "    node = head\n",
    "    while node is not None:\n",
    "        q.append(node.val)\n",
    "        node = node.next\n",
    "        \n",
    "    while len(q) > 1:\n",
    "        if q.pop(0) != q.pop():\n",
    "            return False\n",
    "        \n",
    "    return True"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 37,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "False"
      ]
     },
     "execution_count": 37,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "isPalindrome(node_1)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 38,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "True"
      ]
     },
     "execution_count": 38,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "isPalindrome(node_3)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Accepted\t172 ms\t24.1 MB\tpython3"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 풀이 2. 데크를 이용한 최적화"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 39,
   "metadata": {},
   "outputs": [],
   "source": [
    "import collections"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 40,
   "metadata": {},
   "outputs": [],
   "source": [
    "def isPalindrome(head: ListNode) -> bool:\n",
    "    q = collections.deque()\n",
    "    \n",
    "    if not head:\n",
    "        return True\n",
    "    \n",
    "    node = head\n",
    "    while node is not None:\n",
    "        q.append(node.val)\n",
    "        node = node.next\n",
    "        \n",
    "    while len(q) > 1:\n",
    "        if q.popleft() != q.pop():\n",
    "            return False\n",
    "        \n",
    "    return True"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 41,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "False"
      ]
     },
     "execution_count": 41,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "isPalindrome(node_1)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 42,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "True"
      ]
     },
     "execution_count": 42,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "isPalindrome(node_3)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Accepted\t72 ms\t24.3 MB\tpython3"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 풀이 3. 고를 이용한 데크 구현 \n",
    "\n",
    "고 모름"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 풀이 4. 런너를 이용한 우아한 풀이"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 43,
   "metadata": {},
   "outputs": [],
   "source": [
    "def isPalindrome(head: ListNode) -> bool:\n",
    "    rev = None\n",
    "    slow = fast = head\n",
    "    \n",
    "    while fast and fast.next:\n",
    "        fast = fast.next.next\n",
    "        rev, rev.next, slow = slow, rev, slow.next\n",
    "    if fast:\n",
    "        slow = slow.next\n",
    "    \n",
    "    while rev and rev.val == slow.val:\n",
    "        slow, rev = slow.next, rev.next\n",
    "    return not rev"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 44,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "False"
      ]
     },
     "execution_count": 44,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "isPalindrome(node_1)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 45,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "True"
      ]
     },
     "execution_count": 45,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "isPalindrome(node_3)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Accepted\t72 ms\t24.3 MB\tpython3"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.8.2"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 4
}