היתרונות של מערך בג'אווה

1. הקדמה

במאמר זה נבחן כיצד ליצור תמורות של מערך.

ראשית נגדיר מהי תמורה. שנית, נבחן כמה אילוצים. ושלישית, נבחן שלוש דרכים לחישבן: רקורסיבית, איטרטיבית ואקראית.

אנו נתמקד ביישום ב- Java ולכן לא נפרט הרבה על מתמטיקה.

2. מהי תמורה?

תמורה של סט היא סידור מחדש של יסודותיו. סט המורכב מ נ לאלמנטים יש n! תמורות. פה n! הוא הפקטוריאל, שהוא תוצר של כל המספרים השלמים החיוביים הקטנים או שווים ל- נ.

2.1. דוגמא

מערך המספרים השלמים [3,4,7] כולל שלושה אלמנטים ושישה תמורות:

n! = 3! = 1 x 2 x 3 = 6

תמורות: [3,4,7]; [3,7,4]; [4,7,3]; [4,3,7]; [7,3,4]; [7,4,3]

2.2. אילוצים

מספר התמורות גדל במהירות עם נ. אמנם לוקח כמה שניות בלבד ליצור את כל התמורות של עשרה אלמנטים, אך ייקח שבועיים ליצור את כל התמורות של 15 אלמנטים:

3. אלגוריתמים

3.1. אלגוריתם רקורסיבי

האלגוריתם הראשון שאנחנו מסתכלים עליו הוא האלגוריתם של Heap. זהו אלגוריתם רקורסיבי המייצר את כל התמורות על ידי החלפת אלמנט אחד לאיטרציה.

מערך הקלט ישונה. אם איננו רוצים בכך, עלינו ליצור עותק של המערך לפני שנקרא לשיטה:

print public public static public AllRecursive (int n, T [] יסודות, תו תו) {if (n == 1) {printArray (יסודות, תיחום); } אחר {for (int i = 0; i <n-1; i ++) {printAllRecursive (n - 1, יסודות, תוחם); אם (n% 2 == 0) {החלפה (אלמנטים, i, n-1); } אחר {החלפה (אלמנטים, 0, n-1); }} printAllRecursive (n - 1, אלמנטים, תוחם); }} 

השיטה משתמשת בשתי שיטות עוזרות:

החלפת חלל פרטית (קלט T [], int a, int b) {T tmp = קלט [a]; קלט [a] = קלט [b]; קלט [b] = tmp; }
ריק ריק printArray (קלט T []) {System.out.print ('\ n'); עבור (int i = 0; i <input.length; i ++) {System.out.print (קלט [i]); }} 

הנה, אנו כותבים את התוצאה ל System.outעם זאת, אנו יכולים לאחסן את התוצאה בקלות במערך או ברשימה במקום זאת.

3.2. אלגוריתם איטרטיבי

ניתן ליישם את האלגוריתם של Heap באמצעות איטרציות:

int [] אינדקסים = int int [n]; int [] אינדקסים = int int [n]; עבור (int i = 0; i <n; i ++) {אינדקסים [i] = 0; } printArray (אלמנטים, תוחם); int i = 0; ואילו (i <n) {if (אינדקסים [i] <i) {swap (אלמנטים, i% 2 == 0? 0: אינדקסים [i], i); printArray (אלמנטים, תוחם); אינדקסים [i] ++; i = 0; } אחר {אינדקסים [i] = 0; i ++; }} 

3.3. תמורות בסדר לקסיקוגרפי

אם האלמנטים דומים, נוכל ליצור תמורות ממוינות לפי הסדר הטבעי של האלמנטים:

סטטי ציבורי  בטל printAllOrdered (אלמנטים T [], תו אות) {Arrays.sort (אלמנטים); יש בוליאני Next = true; while (hasNext) {printArray (אלמנטים, תוחם); int k = 0, l = 0; hasNext = false; עבור (int i = elements.length - 1; i> 0; i--) {if (יסודות [i] .compareTo (יסודות [i - 1])> 0) {k = i - 1; hasNext = נכון; לשבור; }} עבור (int i = elements.length - 1; i> k; i--) {if (יסודות [i] .compareTo (יסודות [k])> 0) {l = i; לשבור; }} החלפה (אלמנטים, k, l); Collections.reverse (Arrays.asList (elements) .subList (k + 1, elements.length)); }} 

לאלגוריתם זה יש לַהֲפוֹך פעולה בכל איטרציה ולכן היא פחות יעילה במערכים מאשר האלגוריתם של Heap.

3.4. אלגוריתם אקראי

אם נ הוא גדול, אנחנו יכולים ליצור תמורה אקראית על ידי דשדוש המערך:

Collections.shuffle (Arrays.asList (אלמנטים));

אנו יכולים לעשות זאת מספר פעמים כדי ליצור מדגם של תמורות.

אנו עשויים ליצור את אותן תמורות יותר מפעם אחת, לערכים גדולים של נ, הסיכויים ליצור את אותה תמורה פעמיים נמוכים.

4. מסקנה

ישנן דרכים רבות ליצור את כל התמורות של מערך. במאמר זה ראינו את האלגוריתם של הרמה הרקורסיבית והאיטראטיבית וכיצד ליצור רשימה ממוינת של תמורות.

לא ניתן לייצר את כל התמורות עבור מערכים גדולים, לכן נוכל ליצור תמורות אקראיות במקום.

היישום של כל קטעי הקוד במאמר זה נמצא במאגר Github שלנו.


$config[zx-auto] not found$config[zx-overlay] not found