ﺑﺎﺳﻤﻪ ﺗﻌﺎﻟﻲ
ﭘﺎﺳﺨﻨﺎﻣﻪ اﻣﺘﺤﺎن ﭘﺎﻳﺎن ﺗﺮم درس داده ﺳﺎﺧﺘﺎرﻫﺎ و اﻟﮕﻮرﻳﺘﻢﻫﺎ
ﻗﺴﻤﺖ اول :داده ﺳﺎﺧﺘﺎرﻫﺎ و اﻟﮕﻮرﻳﺘﻢﻫﺎ در ﺗﺌﻮري
.1ﺑﻪ آراﻳﻪي ] A[1..nﻳﻚ آراﻳﻪي wigglyﮔﻔﺘﻪ ﻣﻲﺷﻮد اﮔﺮ
ሾ2݊ + 1ሿܣ ≥ ሾ2݊ሿܣ ∧ ሾ2݊ሿܣ ≤ ሾ2݊ − 1ሿܣ … ሾ5ሿܣ ≥ ሾ4ሿܣ ∧ ሾ4ሿܣ ≤ ሾ3ሿܣ ∧ ሾ3ሿܣ ≥ ሾ2ሿܣ ∧ ሾ2ሿܣ ≤ ሾ1ሿܣ
اﻟﮕﻮرﻳﺘﻤﻲ ﻛﺎرآﻣﺪ اراﻳﻪ دﻫﻴﺪ ﻛﻪ ﺑﺎ ﮔﺮﻓﺘﻦ ﻳﻚ آراﻳﻪ ﻣﺮﺗﺐ ﺷﺪه ﺑﻪ ﻋﻨﻮان ورودي ،آراﻳﻪاي ﺑﺎ ﺧﺎﺻﻴﺖ ذﻛﺮﺷﺪه را ﺑﻪ ﻋﻨﻮان ﺧﺮوﺟﻲ
ﺑﺮﮔﺮداﻧﺪ .زﻣﺎن اﺟﺮاي اﻟﮕﻮرﻳﺘﻢ ﺧﻮد را ﺗﺤﻠﻴﻞ ﻛﻨﻴﺪ.
ﻛﺎﻓﻲ اﺳﺖ رﺷﺘﻪ دﺳﺘﻮرات زﻳﺮ را ﺑﺎ ) O(nزﻣﺎن اﺟﺮا و ) O(1ﺣﺎﻓﻈﻪي اﺿﺎﻓﻲ اﺟﺮا ﻛﻨﻴﻢ:
)for (i = 1; i < n – 1; i += 2
;)]swap(A[i],A[i+1
.2ﻧﺸﺎن دﻫﻴﺪ دوﻣﻴﻦ ﻋﻨﺼﺮ ﻳﻚ آراﻳﻪ از ﻧﻈﺮ ﺑﺰرﮔﻲ ﻣﻘﺪار ﻛﻠﻴﺪ را ﻣﻲﺗﻮان ﺑﺎ − 2ۀlgnڿ n +ﻣﻘﺎﻳﺴﻪ ﻳﺎﻓﺖ.
ﺑﺎ روﻳﻪاي ﻣﺸﺎﺑﻪ ﺟﺎم ﺣﺬﻓﻲ ﻋﻤﻞ ﻣﻲﻛﻨﻴﻢ :ﻋﻨﺎﺻﺮ را ﺑﻪ دﺳﺘﻪﻫﺎي دوﺗﺎﻳﻲ ﺗﻘﺴﻴﻢ ﻣﻲﻛﻨﻴﻢ ،از ﻫﺮ دﺳﺘﻪ ﺑﺎ ﻳﻚ ﻣﻘﺎﻳﺴﻪ ﺑﺰرﮔﺘﺮﻳﻦ ﻋﻨﺼﺮ را
ﺑﻪ دور ﺑﻌﺪ ﻣﻲﻓﺮﺳﺘﻴﻢ ،ﺑﺎز در دور ﺑﻌﺪ ﻋﻨﺎﺻﺮ را ﺑﻪ دﺳﺘﻪﻫﺎي دوﺗﺎﻳﻲ ﺗﻘﺴﻴﻢ و ﻫﻤﻴﻦ روﻳﻪ را ﺑﺮاي ﻳﺎﻓﺘﻦ ﺑﻴﺸﻴﻨﻪ ﻋﻨﺼﺮ ﺗﻜﺮار ﻣﻲﻛﻨﻴﻢ.
ﺑﺪﻳﻦ ﺗﺮﺗﻴﺐ ﺑﺎ ﻳﻚ درﺧﺖ دودوﻳﻲ ،ﻋﻨﺼﺮ ﺑﻴﺸﻴﻨﻪ را ﺑﺎ n – 1ﻣﻘﺎﻳﺴﻪ ﻣﻲﻳﺎﺑﻴﻢ .دوﻣﻴﻦ ﻋﻨﺼﺮ ﺑﻪ ﻟﺤﺎظ ﺑﺰرﮔﻲ در اﻳﻦ درﺧﺖ ﻓﻘﻂ ﻣﻲﺗﻮاﻧﺪ
ﺗﻮﺳﻂ ﺑﺰرﮔﺘﺮﻳﻦ ﻋﻨﺼﺮ ﺣﺬف ﺷﻮد ،ﭘﺲ ﺣﺘﻤﺎ ﺑﺎ آن ﻣﻘﺎﻳﺴﻪ ﺷﺪه ،ﻳﻌﻨﻲ ﻣﻴﺘﻮان ﺑﺎ ﻳﺎﻓﺘﻦ ﺑﺰرﮔﺘﺮﻳﻦ ﻋﻨﺼﺮ از ﺑﻴﻦ ﻋﻨﺎﺻﺮي ﻛﻪ ﺑﺎ ﺑﺰرﮔﺘﺮﻳﻦ
ﻋﻨﺼﺮ ﻣﻘﺎﻳﺴﻪ ﺷﺪه اﻧﺪ )ﻛﻪ ﺗﻌﺪاد آﻧﻬﺎ ﺑﺮاﺑﺮ ارﺗﻔﺎع درﺧﺖ ﻳﻌﻨﻲ ) log(nاﺳﺖ( دوﻣﻴﻦ ﻋﻨﺼﺮ را ﺑﻴﺎﺑﻴﻢ ﻛﻪ اﻳﻦ ﻛﺎر ﻫﻢ ﺑﺎ log(n)-1ﻣﻘﺎﻳﺴﻪ
ﻣﻤﻜﻦ اﺳﺖ.
.3اﮔﺮ ﻋﻨﺼﺮ دﻟﺨﻮاﻫﻲ را در ﻳﻚ درﺧﺖ ﻗﺮﻣﺰ-ﺳﻴﺎه دﻟﺨﻮاه insertﻛﺮده و ﺳﭙﺲ ﻫﻤﺎن ﻋﻨﺼﺮ را deleteﻛﻨﻴﻢ ،آﻳﺎ درﺧﺖ ﺣﺎﺻﻞ
ﻫﻤﻮاره ﻫﻤﺎن درﺧﺖ اوﻟﻴﻪ ﺧﻮاﻫﺪ ﺑﻮد؟ ﭼﺮا؟
ﺧﻴﺮ .ﻣﺜﺎل ﻧﻘﺾ:
٣
٢
٢
٣
Delete 1
٣
١
Rotation
٢
Insert 1
٣
٢
١
.4ﻳﻚ ﺻﻒ را ﺑﺎ اﺳﺘﻔﺎده از دو ﭘﺸﺘﻪ ﺑﻪ ﻧﺤﻮي ﭘﻴﺎده ﺳﺎزي ﻛﻨﻴﺪ ﻛﻪ ﻫﺰﻳﻨﻪي ﺳﺮﺷﻜﻦ ﻋﻤﻠﻴﺎت enqueueو dequeueاز )θ(1
ﺑﺎﺷﺪ .ﻋﻼوه ﺑﺮ ﺗﺸﺮﻳﺢ ﻛﺎﻣﻞ ﭘﻴﺎده ﺳﺎزي ،ﻫﺰﻳﻨﻪي ﺳﺮﺷﻜﻦ را ﻧﻴﺰ ﻣﺤﺎﺳﺒﻪ ﻧﻤﺎﻳﻴﺪ.
ﺑﺮاي ﻫﺮ ﻋﻤﻞ enqueueﻋﻨﺼﺮ ﺟﺪﻳﺪ را در ﭘﺸﺘﻪي اول Pushﻣﻲﻛﻨﻴﻢ .ﺑﺮاي ﻫﺮ ﻋﻤﻞ dequeueاﮔﺮ ﭘﺸﺘﻪي دوم ﺧﺎﻟﻲ ﻧﺒﻮد
ﻋﻨﺼﺮ ﺑﺎﻻي آن را Popﻣﻲﻛﻨﻴﻢ و ﺑﻪ ﻋﻨﻮان ﭘﺎﺳﺦ ﺑﺮﻣﻲﮔﺮداﻧﻴﻢ ،و اﮔﺮ ﺧﺎﻟﻲ ﺑﻮد ﻗﺒﻞ از اﻳﻦ ﻛﺎر اﺑﺘﺪا ﻫﻤﻪي ﻋﻨﺎﺻﺮ ﻣﻮﺟﻮد در ﭘﺸﺘﻪ
اول را ﻳﻜﻲ ﻳﻜﻲ از آن Popﻛﺮده و در ﭘﺸﺘﻪي دوم Pushﻣﻲﻛﻨﻴﻢ .ﺗﻮﺟﻪ ﻛﻨﻴﺪ ﻫﻴﭻ ﮔﺎه ﻋﻨﺎﺻﺮ را از ﭘﺸﺘﻪي دوم ﺑﻪ اول ﺑﺮ ﻧﻤﻲ-
ﮔﺮداﻧﻴﻢ .در اﻳﻦ ﻓﺮاﻳﻨﺪ ﻫﺮ ﻋﻨﺼﺮ دﻗﻴﻘﺎ ﻳﻚ ﺑﺎر ﺑﻪ ﭘﺸﺘﻪي اول Pushﻣﻴﺸﻮد ،ﻳﻚ ﺑﺎر از آن Popﻣﻲﺷﻮد ،ﻳﻚ ﺑﺎر در ﭘﺸﺘﻪي دوم
Pushﻣﻲﺷﻮد و ﻳﻚ ﺑﺎر از آن Popﻣﻲﺷﻮد ،ﻳﻌﻨﻲ ﺑﺮاي ﻫﺮ ﻋﻨﺼﺮ 4واﺣﺪ ﻫﺰﻳﻨﻪ ﻣﻲﻛﻨﻴﻢ ،ﭘﺲ ﺳﺮﺷﻜﻦ ﻫﺰﻳﻨﻪي ﻫﺮ ﻋﻤﻞ )O(1
اﺳﺖ.
.5آراﻳﻪاي از اﻋﺪاد ﻃﺒﻴﻌﻲ دارﻳﻢ .اﻟﮕﻮرﻳﺘﻤﻲ ﭘﻴﺸﻨﻬﺎد ﻛﻨﻴﺪ ﻛﻪ در ) θ(݊ଶﻛﻨﺘﺮل ﻛﻨﺪ ﻛﻪ آﻳﺎ ﺳﻪ ﻋﺪد در آراﻳﻪ وﺟﻮد دارﻧﺪ ﻛﻪ ﻣﻘﺎدﻳﺮ
آنﻫﺎ ﻧﺸﺎندﻫﻨﺪهي ﻃﻮل اﺿﻼع ﻣﺜﻠﺚ ﻗﺎﻳﻢ اﻟﺰاوﻳﻪ ﺑﺎﺷﻨﺪ ،و در ﺻﻮرت وﺟﻮد آنﻫﺎ را ﺑﺮﮔﺮداﻧﺪ.
اﺑﺘﺪا ﻫﺮ ﻋﻨﺼﺮ را ﺑﺎ ﻣﺮﺑﻊ آن ﺟﺎﻳﮕﺰﻳﻦ ﻣﻲﻛﻨﻴﻢ .ﻛﺎﻓﻲ اﺳﺖ در آراﻳﻪي ﺟﺪﻳﺪ ﺳﻪ ﻋﻨﺼﺮ را ﺑﻴﺎﺑﻴﻢ ﻛﻪ ﻋﻨﺼﺮ اول ﺑﺮاﺑﺮ ﻣﺠﻤﻮع دو ﻋﻨﺼﺮ
ﺑﻌﺪ ﺷﻮد .ﺑﺮاي اﻳﻦ ﻛﺎر ﻋﻨﺎﺻﺮ آراﻳﻪ را ﻣﺮﺗﺐ ﻣﻲﻛﻨﻴﻢ و آن را آراﻳﻪي Aﻣﻲﻧﺎﻣﻴﻢ .ﺳﭙﺲ روﻳﻪي زﻳﺮ را ﺑﺮ روي آن اﺟﺮا ﻣﻲﻛﻨﻴﻢ:
{ )for (i = 0; i < n; i++
;int p1 = 0, p2 = i – 1
)while (p1 < i && p2 > p1
;if (A[p1] + A[p2] > A[i]) p2--
else
;if (A[p1] + A[p2] < A[i]) p1++
else
;)]return (A[p1], A[p2], A[i
}
.6ﻓﺮض ﻛﻨﻴﺪ ﻳﻚ درﺧﺖ دودوﻳﻲ ﺟﺴﺘﺠﻮ ﻣﺜﻞ Tﺑﺎ nراس داده ﺷﺪه اﺳﺖ .در اﻳﻦ ﻟﺤﻈﻪ ﭼﻨﺪ Rotationدر Tاﻣﻜﺎن ﭘﺬﻳﺮ اﺳﺖ؟
ﭼﺮا؟ )ﺗﻮﺟﻪ ﻛﻨﻴﺪ ﻛﻪ ﻣﻲﺧﻮاﻫﻴﻢ ﻓﻘﻂ ﻳﻚ Rotationاﻧﺠﺎم دﻫﻴﻢ ﻧﻪ دﻧﺒﺎﻟﻪاي از Rotationﻫﺎ(.
ﺑﺮ روي ﻫﺮ ﻳﺎل درﺧﺖ ﻛﻪ ﮔﺮه ﭘﺪر را ﺑﻪ ﻓﺮزﻧﺪ ﺳﻤﺖ ﭼﭙﺶ وﺻﻞ ﻣﻴﻜﻨﺪ ﻓﻘﻂ ﻣﻲﺗﻮان ﭼﺮﺧﺶ ﺑﻪ راﺳﺖ اﻧﺠﺎم داد ،و ﺑﺮ روي ﻳﺎﻟﻬﺎﻳﻲ
ﻛﻪ ﮔﺮه ﭘﺪر را ﺑﻪ ﻓﺮزﻧﺪ ﺳﻤﺖ راﺳﺖ وﺻﻞ ﻣﻴﻜﻨﻨﺪ ﻓﻘﻂ ﻣﻴﺘﻮان ﭼﺮﺧﺶ ﺑﻪ ﭼﭗ اﻧﺠﺎم داد .ﭘﺲ ﺗﻌﺪاد ﻛﻞ ﭼﺮﺧﺶﻫﺎي ﻣﻤﻜﻦ ﺑﺮاﺑﺮ
اﺳﺖ ﺑﺎ ﺗﻌﺪاد ﻳﺎﻟﻬﺎ ﻳﻌﻨﻲ n-1
.7ﻫﺮ ﻳﻚ از ﻛﺪﻫﺎي زﻳﺮ ﺑﻪ زﺑﺎن Javaﺑﺮاي اﺟﺮاي اﻟﮕﻮرﻳﺘﻢﻫﺎي ﻣﺘﻔﺎوﺗﻲ ﻧﻮﺷﺘﻪ ﺷﺪهاﻧﺪ ﻛﻪ ﻋﺪد ﻃﺒﻴﻌﻲ nرا ﺑﻪ ﻋﻨﻮان ورودي درﻳﺎﻓﺖ
ﻛﺮده و ﺑﻪ ﻋﻨﻮان ﺧﺮوﺟﻲ رﺷﺘﻪاي ﺑﺎ ﻃﻮل 2ﺷﺎﻣﻞ ﻛﺎراﻛﺘﺮﻫﺎي aرا ﺑﺮ ﻣﻲﮔﺮداﻧﺪ .زﻣﺎن اﺟﺮاي ﻫﺮﻳﻚ را ﻣﺤﺎﺳﺒﻪ و ﻣﻘﺎﻳﺴﻪ ﻛﻨﻴﺪ.
)ﻳﺎدآوري :ﭼﺴﺒﺎﻧﺪن دو رﺷﺘﻪ ﺑﻪ ﻫﻢ در Javaﻧﻴﺎزﻣﻨﺪ زﻣﺎﻧﻲ ﻣﺘﻨﺎﺳﺐ ﺑﺎ ﻣﺠﻤﻮع ﻃﻮل دو رﺷﺘﻪ اﺳﺖ(
{ )public String m1(int n
;"String s = "a
)for (int i = 0; i < n; i++
;s = s + s
;return s
}
I.
ିܖ
) ܖ(۽ = ା − ܖ ܑା =
ୀ
{ )public String m2(int n
;"" = String s
int N = 1 << n; // 2^n
)for (int i = 0; i < N; i++
;"s = s + "a
;return s
}
ܖ + )ܖ (ۼ) + ۼ(
=
൯ܖ൫۽ =
ۼ
ିۼ
ୀ
ୀ
II.
= ܑ (ܑ + ) =
{ )public String m3(int n
;"if (n == 0) return "a
;)else return m3(n-1) + m3(n-1
}
ܖ − ) + ܖ(܂) = ܖ(܂
III.
ﺑﻨﺎﺑﺮ ﺗﺤﻠﻴﻞ درﺧﺘﻲ ،ﻣﻴﺪاﻧﻴﻢ اﻳﻦ درﺧﺖ nﺳﻄﺢ دارد و در ﻫﺮ ﺳﻄﺢ ﻣﺠﻤﻮع ﻫﺰﻳﻨﻪﻫﺎ ܖ ﺧﻮاﻫﺪ ﺑﻮد ،ﭘﺲ ﭘﺎﺳﺦ ) ܖ ܖ(۽ ﺧﻮاﻫﺪ ﺑﻮد.
ﻗﺴﻤﺖ دوم :داده ﺳﺎﺧﺘﺎرﻫﺎ و اﻟﮕﻮرﻳﺘﻢﻫﺎ در ﻛﺎرﺑﺮد
ﺗﻮﺿﻴﺢ
ﺳﺎﻳﺖ facebookﻳﻚ ﺧﺪﻣﺖ ﻧﺴﺒﺘﺎ ﺟﺪﻳﺪ اﻳﻨﺘﺮﻧﺘﻲ اﺳﺖ ﻛﻪ در آن ﻫﺮ ﻛﺎرﺑﺮ ﻣﻲﺗﻮاﻧﺪ ﭘﺲ از ﺛﺒﺖ ﻧﺎم ﻳﻚ ﺣﺴﺎب ﻛﺎرﺑﺮي ﺑﻪ ﻧﺎم ﺧﻮد ﺑﺎز
ﻛﻨﺪ و از ﻃﺮﻳﻖ آن ﻣﻄﺎﻟﺐ ﺟﺎﻟﺐ و ﻣﻮرد ﻋﻼﻗﻪاش را ﺑﺮاي دوﺳﺘﺎﻧﺶ ﺑﻪ اﺷﺘﺮاك ﺑﮕﺬارد ،ﺑﺮاي دوﺳﺘﺎﻧﺶ ﭘﻴﺎم ﺑﻔﺮﺳﺘﺪ ﻳﺎ ﺑﺎ دﻳﺪن ﺷﺒﻜﻪ
دوﺳﺘﺎن ﺧﻮد ،دوﺳﺘﺎن دوﺳﺘﺎن ﺧﻮد ،و ...در ﺷﺒﻜﻪي دوﺳﺘﻲﻫﺎ ﺑﻪ ﺟﺴﺘﺠﻮ ﺑﭙﺮدازد .اﻳﺪهي اﻳﻦ ﺳﺎﻳﺖ ﺗﻘﺮﻳﺒﺎ ﻣﺸﺎﺑﻪ ﺳﺮوﻳﺲ ﻗﺒﻠﻲ ﮔﻮﮔﻞ
ﺑﻪ ﻧﺎم Orkutاﺳﺖ ﺑﺎ اﻳﻦ ﺗﻔﺎوت ﻛﻪ اﻳﺪهﻫﺎي ﻣﺘﻨﻮﻋﻲ از ﺟﻤﻠﻪ اﺑﺰارﻫﺎي ﺳﺎدهاي ﺑﺮاي ﺑﺎزيﻫﺎ ﻳﺎ ﺳﺮﮔﺮﻣﻲﻫﺎي ﮔﺮوﻫﻲ ﺑﻪ آن اﺿﺎﻓﻪ ﺷﺪه،
ﺳﺮﻋﺖ ﺑﻪ اﺷﺘﺮاك ﮔﺬاري و ﺳﻬﻮﻟﺖ در درﻳﺎﻓﺖ اﻧﻮاع ﺗﺼﺎوﻳﺮ و ﻓﻴﻠﻢ و ﺻﺪا اﻓﺰاﻳﺶ ﻳﺎﻓﺘﻪ و آن را ﺑﺮاي ﻛﺎرﺑﺮان ﺟﺬابﺗﺮ ﻧﻤﻮده اﺳﺖ.
.1در ﺳﺎﻳﺖ facebookﺗﻌﺪادي ﻛﺎرﺑﺮ ﺛﺒﺖ ﻧﺎم ﻣﻲﻛﻨﻨﺪ .ورود ﻛﺎرﺑﺮان از ﻃﺮﻳﻖ وارد ﻛﺮدن آدرس اﻳﻤﻴﻞ و ﻛﻠﻤﻪي ﻋﺒﻮر اﻧﺠﺎم ﻣﻲﮔﻴﺮد.
روش ﻣﻨﺎﺳﺒﻲ ﭘﻴﺸﻨﻬﺎد ﻛﻨﻴﺪ ﻛﻪ ﺑﺎ اﺳﺘﻔﺎده از آن ﺑﺘﻮاﻧﻴﻢ ﻋﻤﻞ ﻛﻨﺘﺮل ﺗﻄﺎﺑﻖ آدرس اﻳﻤﻴﻞ و ﻛﻠﻤﻪي ﻋﺒﻮر ﻛﺎرﺑﺮان را در زﻣﺎن اﺟﺮا و
ﺑﺎ ﺣﺎﻓﻈﻪي ﻛﺎرآﻣﺪي اﻧﺠﺎم دﻫﻴﻢ .روش ﺧﻮد را ﺑﻪ ﻃﻮر ﻛﺎﻣﻞ ﺗﺤﻠﻴﻞ ﻛﻨﻴﺪ .دﻗﺖ ﻛﻨﻴﺪ ﻛﻪ از اﺑﺘﺪا ﺗﻌﺪاد ﻛﺎرﺑﺮان ﻣﺸﺨﺺ ﻧﻴﺴﺖ و ﻫﺮ
ﻟﺤﻈﻪ ﺑﻪ ﺗﻌﺪاد آﻧﺎن اﻓﺰوده ﻣﻲﺷﻮد ،و روش ﺷﻤﺎ ﺑﺎﻳﺪ اﻳﻦ اﻣﺮ را ﻧﻴﺰ ﭘﺸﺘﻴﺒﺎﻧﻲ ﻛﻨﺪ.
ﺑﺮاي آنﻛﻪ اﻳﻦ ﻛﺎر در ﺣﺎﻟﺖ ﻛﺎرآﻣﺪ اﻧﺠﺎم ﺷﻮد ﺑﺎﻳﺪ رواﻟﻲ اﺳﺘﻔﺎده ﺷﻮد ﻛﻪ اﮔﺮ ﻣﺠﻤﻮع ﻃﻮل ﻳﻚ آدرس اﻳﻤﻴﻞ و ﻛﻠﻤﻪ ﻋﺒﻮر را ﺑﻪ ﻃﻮل n
ﺣﺮف در ﻧﻈﺮ ﺑﮕﻴﺮﻳﻢ ،ﻛﻨﺘﺮل ﺗﻄﺎﺑﻖ ﺣﺘﻲاﻻﻣﻜﺎن ﻧﺰدﻳﻚ ﺑﻪ ) O(nﺑﻪ ﻃﻮل اﻧﺠﺎﻣﺪ .اﻳﻦ ﻛﺎر ﺑﺎ اﺳﺘﻔﺎده از دو ﻧﻮع داده ﺳﺎﺧﺘﺎر اﻣﻜﺎن ﭘﺬﻳﺮ
اﺳﺖ Hash Table :و ﻳﺎ .Trieاﺳﺘﻔﺎده از Trieدر اﻳﻦ ﺧﺼﻮص ﺟﺰﺋﻴﺎت ﺧﺎﺻﻲ ﻧﺪارد وﻟﻲ در ﻫﻨﮕﺎم اﺳﺘﻔﺎده از Hash Tableﺑﺎﻳﺪ دﻗﺖ
ﻛﻨﻴﻢ ﻛﻪ ﻣﺮﺗﺒﺎ ﺑﻪ ﺗﻌﺪاد ﻛﺎرﺑﺮان اﻓﺰوده ﻣﻲﺷﻮد ،ﻟﺬا ﺑﺎﻳﺪ از ﻳﻚ ﺟﺪول ﺑﺎ اﻧﺪازهي ﭘﻮﻳﺎ اﺳﺘﻔﺎده ﻛﻨﻴﻢ ،ﺑﺪﻳﻦ ﻣﻨﻈﻮر ﻫﺮﮔﺎه ﺿﺮﻳﺐ ﭘﺮ ﺑﻮدن
ﺟﺪول از ﻳﻚ ﺣﺪ آﺳﺘﺎﻧﻪ ﮔﺬﺷﺖ ﺑﺎﻳﺪ اﻧﺪازهي ﺟﺪول را دوﺑﺮاﺑﺮ ﻛﻨﻴﻢ ،ﻛﻪ اﻟﺒﺘﻪ ﺑﺎ اﻳﻦ ﻛﺎر ﺗﺎﺑﻊ Hashingﻧﻴﺰ ﻋﻮض ﻣﻲﺷﻮد.
.2در ﺳﺎﻳﺖ facebookﻫﺮ زوج از ﻛﺎرﺑﺮان ﺛﺒﺖ ﻧﺎم ﺷﺪه ﻣﻲﺗﻮاﻧﻨﺪ ﺑﺎ ﺗﻮاﻓﻖ دو ﻃﺮﻓﻪ ،ﻳﻜﺪﻳﮕﺮ را ﺑﻪ ﻋﻨﻮان دوﺳﺖ ﺧﻮد اﺿﺎﻓﻪ ﻛﻨﻨﺪ.
اﺿﺎﻓﻪ ﺷﺪن ﻛﺎرﺑﺮان ﺟﺪﻳﺪ ﻳﺎ اﻳﺠﺎد ﭘﻴﻮﻧﺪ دوﺳﺘﻲ ﺟﺪﻳﺪ ﺑﻴﻦ دو ﻛﺎرﺑﺮ ﻣﻤﻜﻦ اﺳﺖ در ﻫﺮ ﻟﺤﻈﻪ رخ دﻫﺪ .از ﺷﻤﺎ ﺧﻮاﺳﺘﻪ ﺷﺪه ﻳﻚ
ﺑﺮﻧﺎﻣﻪ ﻛﺎرآﻣﺪ در اﺧﺘﻴﺎر اﻳﻦ ﺳﺎﻳﺖ ﻗﺮار دﻫﻴﺪ ﻛﻪ ﻫﺮ ﻟﺤﻈﻪ ﺑﺎ ﮔﺮﻓﺘﻦ دو ﻛﺎرﺑﺮ ﺑﺘﻮاﻧﺪ ﺗﺸﺨﻴﺺ دﻫﺪ آﻳﺎ آنﻫﺎ در ﻳﻚ ﺷﺒﻜﻪي دوﺳﺘﻲ
ﻗﺮار دارﻧﺪ ﻳﺎ ﺧﻴﺮ .دو ﻛﺎرﺑﺮ در ﻳﻚ ﺷﺒﻜﻪي دوﺳﺘﻲ ﻗﺮار دارﻧﺪ اﮔﺮ ﻣﺴﺘﻘﻴﻤﺎ ﺑﺎ ﻳﻜﺪﻳﮕﺮ دوﺳﺖ ﺑﺎﺷﻨﺪ ﻳﺎ زﻧﺠﻴﺮهاي از دوﺳﺘﺎن ﻣﻴﺎﻧﻲ
ﺑﻴﻦ آنﻫﺎ وﺟﻮد داﺷﺘﻪ ﺑﺎﺷﺪ .روﺷﻲ ﺑﺮاي اﻳﻦ ﻛﺎر اراﺋﻪ دﻫﻴﺪ ﻛﻪ ﻋﻼوه ﺑﺮ ﭘﺎﺳﺦ ﺑﻪ اﻳﻦ ﭘﺮﺳﺶ ﺑﺘﻮاﻧﺪ اﻓﺰوده ﺷﺪن ﻛﺎرﺑﺮان ﻳﺎ ﭘﻴﻮﻧﺪﻫﺎي
دوﺳﺘﻲ ﺟﺪﻳﺪ را ﻧﻴﺰ ﭘﺸﺘﻴﺒﺎﻧﻲ ﻛﻨﺪ .ﺳﭙﺲ آن را ﺗﺤﻠﻴﻞ ﻛﻨﻴﺪ.
اﻧﺠﺎم اﻳﻦ ﻓﺮاﻳﻨﺪ ﺑﻪ ﻧﺤﻮ ﻛﺎرآﻣﺪ ﺗﻨﻬﺎ ﺑﺎ اﺳﺘﻔﺎده از Disjoint Setsاﻣﻜﺎن ﭘﺬﻳﺮ اﺳﺖ .ﺛﺒﺖ ﻧﺎم ﻫﺮ ﻛﺎرﺑﺮ ﺟﺪﻳﺪ ﺑﻪ ﻣﻨﺰﻟﻪ ﻳﻚ ﻋﻤﻞ
MakeSetاﺳﺖ ،اﻳﺠﺎد دوﺳﺘﻲ ﺑﻴﻦ دو ﻛﺎرﺑﺮ ﺑﻪ ﻣﻨﺰﻟﻪي Unionﺑﻴﻦ ﻣﺠﻤﻮﻋﻪي آن دو اﺳﺖ ،و در ﺻﻮرﺗﻲ دو ﻛﺎرﺑﺮ در ﻳﻚ ﺷﺒﻜﻪي
دوﺳﺘﻲ ﻗﺮار دارﻧﺪ ﻛﻪ FindSetﻫﺮ دوي آنﻫﺎ ﻳﻜﺴﺎن ﺑﺎﺷﺪ .دﻗﺖ ﻛﻨﻴﺪ ﺗﻨﻬﺎ ﺑﻪ ﺣﺪاﻛﺜﺮ ﻛﺎرآﻣﺪي ﻣﻲرﺳﻴﻢ ﻛﻪ از روش ﻓﺸﺮدهﺳﺎزي ﻣﺴﻴﺮ
اﺳﺘﻔﺎده ﻛﻨﻴﻢ ،ﻛﻪ در اﻳﻦ ﺻﻮرت اﻧﺠﺎم nﻋﻤﻞ ﺑﺮ روي ﻣﺠﻤﻮﻋﻪﻫﺎ ﺑﻪ ) O(nﺑﺴﻴﺎر ﻧﺰدﻳﻚ ﺧﻮاﻫﺪ ﺑﻮد )در واﻗﻊ ﻋﺪد دﻗﻴﻖ آن ﺑﺮاﺑﺮ اﺳﺖ ﺑﺎ
)) O(n α(nﻛﻪ ﻣﻘﺪار ) α(nدر ﻋﻤﻞ ﺑﺴﻴﺎر ﻧﺰدﻳﻚ ﺑﻪ 1و ﻣﺮﺗﺒﻂ ﺑﺎ ) log*(nاﺳﺖ(.
.3ﺳﺎﻳﺖ facebookدر ﻫﺮ ﻟﺤﻈﻪ ﺑﻪ ﺷﻤﺎ ﺑﻪ ﻋﻨﻮان ﻳﻚ ﻛﺎرﺑﺮ ،ﻳﻚ ﻛﺎرﺑﺮ دﻳﮕﺮ را ﻛﻪ ﺗﺎﻛﻨﻮن ﺑﺎ وي ﭘﻴﻮﻧﺪ دوﺳﺘﻲ ﺑﺮﻗﺮار ﻧﻜﺮدهاﻳﺪ اﻣﺎ ﺑﻪ
اﺣﺘﻤﺎل زﻳﺎد در واﻗﻌﻴﺖ ﺑﺎ ﺷﻤﺎ دوﺳﺖ اﺳﺖ را ﺑﺮاي اﻓﺰودن ﺑﻪ ﻓﻬﺮﺳﺖ دوﺳﺘﺎﻧﺘﺎن ﭘﻴﺸﻨﻬﺎد ﻣﻲﻛﻨﺪ .ﻳﻚ ﻓﺮاﻳﻨﺪ ﺑﺮاي اﻧﺠﺎم اﻳﻦ اﻣﺮ
ﺑﺪﻳﻦ ﺻﻮرت اﺳﺖ ﻛﻪ facebookدر ﻫﺮ ﻟﺤﻈﻪ ﺑﺮاي ﺷﻤﺎ ،ﻣﺠﻤﻮﻋﻪاي از ﻛﺎرﺑﺮان ﻛﻪ ﺗﺎﻛﻨﻮن دوﺳﺘﺘﺎن ﻧﺸﺪهاﻧﺪ وﻟﻲ اﺣﺘﻤﺎل دوﺳﺘﻲ
دارﻧﺪ را ﻧﮕﺎه ﻣﻲدارد و ﺑﻪ ﻫﺮ ﻳﻚ از آنﻫﺎ ﻳﻚ ﻋﺪد ﺑﻪ ﻋﻨﻮان »اﺣﺘﻤﺎل دوﺳﺘﻲ« ﻧﺴﺒﺖ ﻣﻲدﻫﺪ .ﻣﻘﺪار اﺣﺘﻤﺎل دوﺳﺘﻲ ﺑﺮاي ﻫﺮ ﻳﻚ از
اﻳﻦ اﻓﺮاد در ﻃﻮل زﻣﺎن ﻣﻲﺗﻮاﻧﺪ اﻓﺰاﻳﺶ ﻳﺎﺑﺪ .از ﺑﻴﻦ ﻛﺎرﺑﺮان اﻳﻦ ﻣﺠﻤﻮﻋﻪ facebook ،ﻛﺴﻲ را ﺑﻪ ﺷﻤﺎ ﭘﻴﺸﻨﻬﺎد ﻣﻲﻛﻨﺪ ﻛﻪ اﺣﺘﻤﺎل
دوﺳﺘﻲ ﺑﺎﻻﺗﺮي دارد .اﮔﺮ ﺷﻤﺎ اﻳﻦ ﭘﻴﺸﻨﻬﺎد را ﻗﺒﻮل ﻛﺮدﻳﺪ ،ﻛﺎرﺑﺮ ﭘﻴﺸﻨﻬﺎد ﺷﺪه ﺑﻪ ﻓﻬﺮﺳﺖ دوﺳﺘﺎﻧﺘﺎن اﺿﺎﻓﻪ ﻣﻲﺷﻮد و در ﺻﻮرت ﻋﺪم
ﻗﺒﻮل ،ﻛﺎرﺑﺮ ﭘﻴﺸﻨﻬﺎدي از ﻣﺠﻤﻮﻋﻪ ﺣﺬف ﻣﻲﺷﻮد و ﻛﺎرﺑﺮ ﺑﺎ اﺣﺘﻤﺎل دوﺳﺘﻲ ﺑﺎﻻﺗﺮ ﺑﻌﺪي ﺑﻪ ﺷﻤﺎ ﭘﻴﺸﻨﻬﺎد ﻣﻲﺷﻮد .روﺷﻲ ﺑﺮاي اﻳﻦ
ﻛﺎر ﭘﻴﺸﻨﻬﺎد دﻫﻴﺪ و آن را ﺗﺤﻠﻴﻞ ﻛﻨﻴﺪ .ﺗﻮﺟﻪ ﻛﻨﻴﺪ اﻳﻦ روش ﺑﺎﻳﺪ ﻋﻤﻞ اﻓﺰاﻳﺶ اﺣﺘﻤﺎل دوﺳﺘﻲ ﻳﻚ ﻛﺎرﺑﺮ را ﻧﻴﺰ ﭘﺸﺘﻴﺒﺎﻧﻲ ﻛﻨﺪ.
ﺑﺮاي اﻳﻦ ﻛﺎر از دو داده ﺳﺎﺧﺘﺎر Treapﻳﺎ Priority Queueﻛﻪ ﻫﺮ دو ﺧﺼﻮﺻﻴﺎت MaxHeapرا دارﻧﺪ ﻣﻲﺗﻮاﻧﻴﻢ اﺳﺘﻔﺎده ﻛﻨﻴﻢ .ﻣﺰﻳﺖ
اﺳﺘﻔﺎده از Treapآن اﺳﺖ ﻛﻪ ﺟﺴﺘﺠﻮي ﻳﻚ ﻋﻨﺼﺮ ﺑﺮاي اﻓﺰاﻳﺶ اﺣﺘﻤﺎل دوﺳﺘﻲ ﻧﻴﺰ ﺑﻪ ﺧﺎﻃﺮ آن ﻛﻪ وﻳﮋﮔﻲﻫﺎي درﺧﺖ دودوﻳﻲ ﺟﺴﺘﺠﻮ
را ﻧﻴﺰ در ﺑﺮ دارد از ) O(log nﺧﻮاﻫﺪ ﺑﻮد ،در ﺻﻮرﺗﻲ ﻛﻪ اﮔﺮ ﺑﺨﻮاﻫﻴﻢ در Priority Queueﻳﻚ ﻋﻨﺼﺮ را ﺟﺴﺘﺠﻮ ﻛﻨﻴﻢ ﺑﺎﻳﺪ از ﻳﻚ
ﻟﻴﺴﺖ اﺿﺎﻓﻪ اﺳﺘﻔﺎده ﻛﻨﻴﻢ ﻛﻪ آدرس ﻋﻨﺼﺮ در Priority Queueرا ﺑﺮﮔﺮداﻧﺪ .در ﻫﺮ دو داده ﺳﺎﺧﺘﺎر ﭘﻴﺪا ﻛﺮدن ﻋﻨﺼﺮي ﺑﺎ ﺑﺎﻻﺗﺮﻳﻦ
اﺣﺘﻤﺎل دوﺳﺘﻲ ﺑﺎ ) O(1اﻣﻜﺎن ﭘﺬﻳﺮ اﺳﺖ ،و درج ﻋﻨﺼﺮ ﺟﺪﻳﺪ ﻳﺎ اﻓﺰاﻳﺶ اﺣﺘﻤﺎل دوﺳﺘﻲ ﺑﺎ ) O(log nﻣﻤﻜﻦ ﻣﻲﺑﺎﺷﺪ.
.4از دﻳﮕﺮ ﻗﺎﺑﻠﻴﺖﻫﺎي facebookﻧﻤﺎﻳﺶ ﺗﻌﺪاد دوﺳﺘﺎن ﻣﺸﺘﺮك ﺑﻴﻦ ﻫﺮ زوج ﻛﺎرﺑﺮ اﺳﺖ .روﺷﻲ اراﺋﻪ دﻫﻴﺪ ﻛﻪ اﻳﻦ ﺳﺎﻳﺖ ﺑﺘﻮاﻧﺪ در
ﻳﻚ داده ﺳﺎﺧﺘﺎر ﻛﻪ ﺑﻪ ﻟﺤﺎظ ﺣﺎﻓﻈﻪ ﻛﺎرآﻣﺪ اﺳﺖ ،دوﺳﺘﺎن ﻫﺮ ﻛﺎرﺑﺮ را ذﺧﻴﺮه ﺳﺎزي ﻛﻨﺪ و ﻫﺮ ﻟﺤﻈﻪ ﺑﺘﻮاﻧﺪ ﺗﻌﺪاد دوﺳﺘﺎن ﻣﺸﺘﺮك
ﻫﺮ دو ﻛﺎرﺑﺮ دﻟﺨﻮاه را اﻋﻼم ﻛﻨﺪ .اﻳﻦ روش ﺑﺎﻳﺪ اﻳﺠﺎد ﻳﺎ ﺣﺬف ﭘﻴﻮﻧﺪﻫﺎي دوﺳﺘﻲ و اﺿﺎﻓﻪ ﻳﺎ ﻛﻢ ﺷﺪن ﻛﺎرﺑﺮان را ﭘﺸﺘﻴﺒﺎﻧﻲ ﻛﻨﺪ .روش
ﺧﻮد را ﺑﻪ ﺻﻮرت ﻛﺎﻣﻞ ﺑﻪ ﻟﺤﺎظ زﻣﺎن و ﺣﺎﻓﻈﻪ ﺗﺤﻠﻴﻞ ﻛﻨﻴﺪ.
اﺑﺘﺪا ﺑﺎﻳﺪ دﻗﺖ ﻛﻨﻴﻢ ﻛﻪ اﺣﺘﻤﺎﻻ ﺗﻌﺪاد دﻓﻌﺎﺗﻲ ﻛﻪ ﺑﺮاي ﻳﻚ ﻛﺎرﺑﺮ دوﺳﺖ ﺟﺪﻳﺪ اﺿﺎﻓﻪ ﻳﺎ از دوﺳﺘﺎن وي ﻛﻢ ﻣﻲﺷﻮد ﺑﺴﻴﺎر ﻛﻤﺘﺮ از ﺗﻌﺪاد
ﭘﺮﺳﺸﻬﺎ در ﻣﻮرد دوﺳﺘﺎن ﻣﺸﺘﺮك وي ﺑﺎ ﻳﻚ ﻛﺎرﺑﺮ دﻳﮕﺮ رخ ﻣﻲدﻫﺪ ،ﺑﻨﺎﺑﺮاﻳﻦ ﺑﻬﺘﺮ اﺳﺖ ﻛﻪ ﺗﻤﺮﻛﺰ ﻣﺎ ﻃﺮاﺣﻲ داده ﺳﺎﺧﺘﺎري ﺑﺎﺷﺪ ﻛﻪ
ﺑﺘﻮاﻧﺪ ﭘﺮﺳﺶ در ﻣﻮرد دوﺳﺘﺎن ﻣﺸﺘﺮك دو ﻛﺎرﺑﺮ را ﺑﻪ ﻧﺤﻮ ﺑﻬﻴﻨﻪاي ﭘﺎﺳﺦ ﮔﻮﻳﺪ .ﻳﻚ راه ﺳﺎده ﺑﺮاي اﻧﺠﺎم اﻳﻦ ﻓﺮاﻳﻨﺪ آن اﺳﺖ ﻛﻪ ﺑﺮاي ﻫﺮ
ﻛﺎرﺑﺮ ،ﻓﻬﺮﺳﺖ دوﺳﺘﺎﻧﺶ ﺑﻪ ﺻﻮرت ﻳﻚ ﻟﻴﺴﺖ ﭘﻴﻮﻧﺪي ذﺧﻴﺮه ﺷﻮد ،اﻟﺒﺘﻪ ﻫﻤﻮاره اﻳﻦ ﻟﻴﺴﺖ ﭘﻴﻮﻧﺪي را ﺑﻪ ﺻﻮرت ﻣﺮﺗﺐ ﻧﮕﻬﺪاري ﻣﻴﻜﻨﻴﻢ.
اﮔﺮ ﺗﻌﺪاد دوﺳﺘﺎن ﻳﻚ ﻛﺎرﺑﺮ nﻧﻔﺮ ﺑﺎﺷﺪ ،اﻓﺰودن ﻳﺎ ﺣﺬف ﭘﻴﻮﻧﺪ دوﺳﺘﻲ ﺑﺮاي وي ) O(nﺑﻪ ﻃﻮل ﺧﻮاﻫﺪ اﻧﺠﺎﻣﻴﺪ .ﺣﺎل اﮔﺮ ﺑﺨﻮاﻫﻴﻢ ﺗﻌﺪاد
دوﺳﺘﺎن ﻣﺸﺘﺮك دو ﻛﺎرﺑﺮ را ﭘﻴﺪا ﻛﻨﻴﻢ ﻛﺎﻓﻲ اﺳﺖ ﻣﺎﻧﻨﺪ ،Merge Sortﻓﻬﺮﺳﺖ دوﺳﺘﺎن آن دو را ﺑﺎ ) O(nادﻏﺎم ﻛﻨﻴﻢ و ﺗﻤﺎم اﻓﺮاد
ﺗﻜﺮاري در اﻳﻦ ادﻏﺎم را ﺑﻪ ﻋﻨﻮان دوﺳﺖ ﻣﺸﺘﺮك اﻋﻼم ﻛﻨﻴﻢ .ﺑﺪﻳﻦ ﺗﺮﺗﻴﺐ اﻧﺠﺎم اﻳﻦ ﻓﺮاﻳﻨﺪ ﻛﺎرآﻣﺪ ﺧﻮاﻫﺪ ﺑﻮد .ﺑﺮاي ﺑﻬﺒﻮد زﻣﺎن ﺣﺬف ﻳﺎ
درج دوﺳﺘﺎن ﻛﺎرﺑﺮ ،ﻣﻲﺗﻮاﻧﻴﻢ ﺑﻪ ﺟﺎي اﺳﺘﻔﺎده از ﻟﻴﺴﺖ ﭘﻴﻮﻧﺪي ،از درﺧﺖ ﻗﺮﻣﺰ-ﺳﻴﺎه ﻛﻤﻚ ﺑﮕﻴﺮﻳﻢ .در اﻳﻦ ﺻﻮرت درج و ﺣﺬف ﭘﻴﻮﻧﺪﻫﺎي
دوﺳﺘﻲ از ) O(log nزﻣﺎن ﻣﻲﺑﺮد ،و ﺑﺎزﻫﻢ ﻣﻲﺗﻮاﻧﻴﻢ ﺑﺎ ﭘﻴﻤﺎﻳﺶ In-Orderدرﺧﺖ ،ﻟﻴﺴﺖ ﻣﺮﺗﺐ ﺷﺪهي دوﺳﺘﺎن ﻫﺮ ﻛﺎرﺑﺮ را ﺑﺮاي ﻋﻤﻞ
ادﻏﺎم داﺷﺘﻪ ﺑﺎﺷﻴﻢ.
»ﻫﻤﭽﻮن ﺳﭙﻴﺪار ،ﺳﺒﺰ و ﺳﺮﻓﺮاز ﺑﺎﺷﻴﺪ«
© Copyright 2026 Paperzz