\documentclass[11pt]{article}
\usepackage{epsfig}
\usepackage{amsfonts}
\usepackage{amssymb}
\usepackage{amstext}
\usepackage{amsmath}
\usepackage{xspace}
\usepackage{theorem}
\usepackage{hyperref}
\usepackage{fullpage}
\usepackage[]{algorithm2e}
\usepackage{framed}
\usepackage{enumitem}
\usepackage{listings}
\newif\ifrubric
\rubrictrue
%\rubricfalse
% This is the stuff for normal spacing
%\makeatletter
% \setlength{\textwidth}{6.5in}
% \setlength{\oddsidemargin}{0in}
% \setlength{\evensidemargin}{0in}
% \setlength{\topmargin}{0.25in}
% \setlength{\textheight}{8.25in}
% \setlength{\headheight}{0pt}
% \setlength{\headsep}{0pt}
% \setlength{\marginparwidth}{59pt}
%
% \setlength{\parindent}{0pt}
% \setlength{\parskip}{5pt plus 1pt}
% \setlength{\theorempreskipamount}{5pt plus 1pt}
% \setlength{\theorempostskipamount}{0pt}
% \setlength{\abovedisplayskip}{8pt plus 3pt minus 6pt}
\usepackage{titlesec}
\titleformat*{\section}{\bfseries}
\titleformat*{\subsection}{\bfseries}
\titleformat*{\subsubsection}{\bfseries}
\titleformat*{\paragraph}{\bfseries}
\titleformat*{\subparagraph}{\bfseries}
% \renewcommand{\section}{\@startsection{section}{1}{0mm}%
% {2ex plus -1ex minus -.2ex}%
% {1.3ex plus .2ex}%
% {\normalfont\Large\bfseries}}%
% \renewcommand{\subsection}{\@startsection{subsection}{2}{0mm}%
% {1ex plus -1ex minus -.2ex}%
% {1ex plus .2ex}%
% {\normalfont\large\bfseries}}%
% \renewcommand{\subsubsection}{\@startsection{subsubsection}{3}{0mm}%
% {1ex plus -1ex minus -.2ex}%
% {1ex plus .2ex}%
% {\normalfont\normalsize\bfseries}}
% \renewcommand\paragraph{\@startsection{paragraph}{4}{0mm}%
% {1ex \@plus1ex \@minus.2ex}%
% {-1em}%
% {\normalfont\normalsize\bfseries}}
% \renewcommand\subparagraph{\@startsection{subparagraph}{5}{\parindent}%
% {2.0ex \@plus1ex \@minus .2ex}%
% {-1em}%
% {\normalfont\normalsize\bfseries}}
%\makeatother
\newenvironment{proof}{{\bf Proof: }}{\hfill\rule{2mm}{2mm}}
\newenvironment{proofof}[1]{{\bf Proof of #1: }}{\hfill\rule{2mm}{2mm}}
\newenvironment{proofofnobox}[1]{{\bf#1: }}{}
\newenvironment{example}{{\bf Example: }}{\hfill\rule{2mm}{2mm}}
%\renewcommand{\thesection}{\lecnum.\arabic{section}}
%\renewcommand{\theequation}{\thesection.\arabic{equation}}
%\renewcommand{\thefigure}{\thesection.\arabic{figure}}
%\renewcommand{\theequation}{\lecnum.\arabic{equation}}
%\renewcommand{\thefigure}{\lecnum.\arabic{figure}}
%\newcounter{LecNum}
%\setcounter{LecNum}{1}
%\newtheorem{fact}{Fact}[LecNum]
\newtheorem{fact}{Fact}
\newtheorem{lemma}[fact]{Lemma}
\newtheorem{theorem}[fact]{Theorem}
\newtheorem{definition}[fact]{Definition}
\newtheorem{corollary}[fact]{Corollary}
\newtheorem{proposition}[fact]{Proposition}
\newtheorem{claim}[fact]{Claim}
\newtheorem{exercise}[fact]{Exercise}
% math notation
\newcommand{\R}{\ensuremath{\mathbb R}}
\newcommand{\Z}{\ensuremath{\mathbb Z}}
\newcommand{\N}{\ensuremath{\mathbb N}}
\newcommand{\F}{\ensuremath{\mathcal F}}
\newcommand{\SymGrp}{\ensuremath{\mathfrak S}}
\newcommand{\size}[1]{\ensuremath{\left|#1\right|}}
\newcommand{\ceil}[1]{\ensuremath{\left\lceil#1\right\rceil}}
\newcommand{\floor}[1]{\ensuremath{\left\lfloor#1\right\rfloor}}
\newcommand{\poly}{\operatorname{poly}}
\newcommand{\polylog}{\operatorname{polylog}}
% anupam's abbreviations
\newcommand{\e}{\epsilon}
\newcommand{\half}{\ensuremath{\frac{1}{2}}}
\newcommand{\junk}[1]{}
\newcommand{\sse}{\subseteq}
\newcommand{\union}{\cup}
\newcommand{\meet}{\wedge}
\newcommand{\prob}[1]{\ensuremath{\text{{\bf Pr}$\left[#1\right]$}}}
\newcommand{\expct}[1]{\ensuremath{\text{{\bf E}$\left[#1\right]$}}}
\newcommand{\Event}{{\mathcal E}}
\newcommand{\mnote}[1]{\normalmarginpar \marginpar{\tiny #1}}
\setenumerate[0]{label=(\alph*)}
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% Document begins here %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
\begin{document}
\noindent {\large {\bf 601.433/633 Introduction to Algorithms} \hfill {{\bf Fall 2024}}}\\
{{\bf Homework \#4}} \hfill {{\bf Due:} October 3, 2024, 9am} \\
\rule[0.1in]{\textwidth}{0.4pt}
Remember: you may work in groups of up to three people, but must write up your solution entirely on your own. Collaboration is limited to discussing the problems -- you may not look at, compare, reuse, etc.~any text from anyone else in the class. Please include your list of collaborators on the first page of your submission. You may use the internet to look up formulas, definitions, etc., but may not simply look up the answers online.
Please include proofs with all of your answers, unless stated otherwise.
\noindent \rule[0.1in]{\textwidth}{0.4pt}
\section{Amortized Analysis (34 points)}
In this problem we have two stacks $A$ and $B$ (recall that a stack allows us to push elements onto it and to pop elements off of it in LIFO order). In what follows, we will use $n$ to denote the number of elements in stack $A$ and use $m$ to denote the number of elements in stack $B$. Suppose that we use these stacks to implement the following operations:
\begin{itemize}
\item \textsc{PushA($x$)}: Push element $x$ onto $A$.
\item \textsc{PushB($x$)}: Push element $x$ onto $B$.
\item \textsc{BigPopA($k$)}: Pop $\min(n,k)$ elements from $A$.
\item \textsc{BigPopB($k$)}: Pop $\min(m,k)$ elements from $B$.
\item \textsc{Move($k$)}: Repeatedly pop one element from $A$ and push it into $B$, until either $k$ elements have been moved or $A$ is empty.
\end{itemize}
We are using the stacks $A$ and $B$ as black boxes -- you may assume that \textsc{PushA}, \textsc{PushB}, \textsc{BigPopA($1$)}, and \textsc{BigPopB($1$)} each take one unit of time (i.e., it takes one time step to push or pop a single element).
Use a potential function argument to prove that the amortized running time of every operation is $O(1)$.
\section{Amortized analysis of 2-3-4 trees (33 points)}
Recall that in a 2-3-4 tree, whenever we insert a new key we immediately split (on our way down the tree) any node we see that is full (has 3 keys in it).
\begin{enumerate}
\item (11 points) Show that in the worst case, the number of splits that we do in a single operation can be $\Omega(\log n)$. In other words, show that for there is a series of $n$ inserts so that the next insert causes $\Omega(\log n)$ splits. You can be a bit informal here --- just explain at a high level what such a sequence would look like and why it would result in $\Omega(\log n)$ splits.
\end{enumerate}
Let's try to get around this worst-case bound by using amortized analysis. We will try to prove that the amortized number of splits is only $O(1)$. Note that this does not mean that the amortized running time of an insert is $O(1)$ (since this is not true); it just means that the amortized number of splits is $O(1)$. So think of ``cost" not as ``time", but as ``number of splits". Since we didn't talk about them in class, feel free to assume there are no delete operations.
\begin{enumerate}[resume]
\item (11 points) Since we only have to split a node when it's full, a natural approach is to have a bank on every node which works as follows. When a node is first created its bank is initialized to $0$. When a node becomes full, we add $1$ to its bank. Then when we split a node we use the $1$ in its bank to pay for the split. In other words, a node's bank is $1$ if the node is full and $0$ otherwise.
This argument unfortunately does not work. Prove that this banking scheme \emph{does not} imply that the amortized number of splits is $O(1)$.
\item (11 points) Show how to modify this argument to work. That is, show how we can use a bank at each node to prove that the amortized number of splits is $O(1)$. Hint: the previous part shows that this bank cannot just equal $1$ if the node is full and $0$ otherwise.
\end{enumerate}
\section{Union-Find (33 points)}
In this problem we'll consider what happens if we change our Union-Find data structure to \emph{not} use path compression. We will still use union-by-rank, but Find operations will no longer compress the tree. More formally, consider the following tree-based data structure. Every element has a parent pointer and a rank value.
\textbf{Make-Set($x$):} Set $x \rightarrow parent := x$ and set $x \rightarrow rank := 0$.
\textbf{Find($x$):} If $x \rightarrow parent == x$ then return $x$. Else return $Find(x \rightarrow parent)$.
\textbf{Union($x, y$):}
\qquad Let $w := Find(x)$ and let $z := Find(y)$.
\qquad If $(w \rightarrow rank) \geq (z \rightarrow rank)$ then set $z \rightarrow parent := w$, else set $w \rightarrow parent := z$.
\qquad If $(w \rightarrow rank) == (z \rightarrow rank)$, set $(w \rightarrow rank) := (w \rightarrow rank) + 1$
\noindent In this problem we will analyze the running time of this variation.
\begin{enumerate}
\item (11 points) Recall that the height of any node $x$ is the maximum over all of the descendants of $x$ of the length of the path from $x$ to that descendant. Prove that for every node $x$, the rank of $x$ is always equal to the height of $x$. Hint: use induction.
\item (11 points) Prove that if $x$ has rank $r$, then there are at least $2^r$ elements in the subtree rooted at $x$ (we did this in class for the more complicated data structure which uses path compression, but now you should do it for this version without path compression).
\item (11 points) Using the previous two parts, prove that every operation (Make-Set, Union, and Find) takes only $O(\log n)$ time (where $n$ is the number of elements, i.e., the number of Make-Set operations).
\end{enumerate}
\end{document}