สำหรับสตริงที่กำหนด ให้โอนองค์ประกอบที่มีตำแหน่งคู่ทั้งหมดไปยังจุดสิ้นสุดของสตริง ขณะถ่ายโอนองค์ประกอบ ให้รักษาลำดับสัมพัทธ์ขององค์ประกอบตำแหน่งคู่และตำแหน่งคี่เหมือนกัน
ตัวอย่างเช่น หากสตริงที่ระบุคือ "a1b2c3d4e5f6g7h8i9j1k2l3m4" ให้แปลงเป็น "abcdefghijklm1234567891234" ในตำแหน่งและความซับซ้อนของเวลา O(n)
มีขั้นตอนดังนี้
-
ตัดสตริงย่อยที่มีขนาดสูงสุดของแบบฟอร์ม 3^k + 1 ออก ในขั้นตอนนี้ เราจะหาจำนวนเต็มที่ไม่ติดลบ k สูงสุด โดยที่ 3^k+1 จะน้อยกว่าหรือเท่ากับ n (ความยาวของสตริง) )
-
ใช้อัลกอริธึมการวนซ้ำของผู้นำวงจร (อธิบายไว้ด้านล่าง) โดยเริ่มจากดัชนี 1, 3, 9…… ไปที่สตริงย่อยนี้ อัลกอริธึมการวนซ้ำของผู้นำวงจรจะถ่ายโอนรายการทั้งหมดของสตริงย่อยนี้ไปยังตำแหน่งที่ถูกต้อง ซึ่งหมายความว่าตัวอักษรทั้งหมดจะถูกย้ายไปยังครึ่งซ้ายของสตริงย่อย และตัวเลขทั้งหมดจะถูกย้ายไปยังครึ่งขวาของสตริงย่อยนี้ .
-
ประมวลผลสตริงย่อยที่เหลือโดยทำซ้ำขั้นตอนที่ 1 และไม่ใช่ 2.
-
ในปัจจุบัน เราจำเป็นต้องรวมสตริงย่อยที่ประมวลผลเข้าด้วยกันเท่านั้น เริ่มจากจุดสิ้นสุดใดๆ (พูดจากซ้าย) เลือกสตริงย่อยสองสตริงและดำเนินการตามขั้นตอนต่อไปนี้ -
-
ตรงข้ามหรือย้อนกลับครึ่งหลังของสตริงย่อยแรก
-
ตรงข้ามหรือย้อนกลับครึ่งแรกของสตริงย่อยที่สอง
-
ตรงข้ามหรือย้อนกลับครึ่งหลังของสตริงย่อยแรกและครึ่งแรกของสตริงย่อยที่สองเข้าด้วยกัน
-
-
ทำซ้ำขั้นตอนที่ # 4 จนกว่าและเว้นแต่จะรวมสตริงย่อยทั้งหมด มันเหมือนกับการรวม k-way โดยที่สตริงย่อยแรกถูกรวมเข้ากับวินาที ผลลัพธ์จะถูกรวมเข้ากับตัวที่สามเป็นต้น
รหัสได้รับด้านล่างตามอัลกอริธึมด้านบน -
// C++ application of above approach #include <bits/stdc++.h> using namespace std; // A utility function to swap characters void swap ( char* a1, char* b1 ) { char t = *a1; *a1 = *b1; *b1 = t; } // A utility function to reverse string str1[low1..high1] void reverse ( char* str1, int low1, int high1 ) { while ( low < high ) { swap(&str1[low1], &str1[high1] ); ++low1; --high1; } } // Cycle leader algorithm to shift all even // positioned elements at the end. void cycleLeader ( char* str1, int shift1, int len1 ) { int j; char item1; for (int i = 1; i < len1; i *= 3 ) { j = i; item1 = str1[j + shift1]; do{ // odd index if ( j & 1 ) j = len1 / 2 + j / 2; // even index or position else j /= 2; // keep the back-up of element at new index or position swap (&str1[j + shift1], &item1); } while ( j != i ); } } // The main function to convert a string. This function // mainly implements cycleLeader() to convert void moveNumberToSecondHalf( char* str1 ) { int k, lenFirst1; int lenRemaining1 = strlen( str1); int shift1 = 0; while ( lenRemaining1) { k = 0; // Step 1: Find the highest prefix // subarray of the form 3^k + 1 while ( pow( 3, k ) + 1 <= lenRemaining1) k++; lenFirst1 = pow( 3, k - 1 ) + 1; lenRemaining1 -= lenFirst1; // Step 2: Implement cycle leader algorithm // for the highest subarray cycleLeader ( str1, shift1, lenFirst1 ); // Step 4.1: Just opposite or reverse the second half of first subarray reverse ( str1, shift1/2, shift1 - 1 ); // Step 4.2: Just opposite or reverse the first half of second sub-string. reverse ( str1, shift1, shift1 + lenFirst1 / 2 - 1 ); // Step 4.3 Just opposite or reverse the second half of first sub-string and first half of second sub-string together reverse ( str1, shift1 / 2, shift1 + lenFirst1 / 2 - 1 ); // Now increase the length of first subarray Shift1 += lenFirst1; } } // Driver program to verify or test above function int main() { char str1[] = "a1b2c3d4e5f6g7"; moveNumberToSecondHalf( str1 ); cout<<str1; return 0; }
ผลลัพธ์
abcdefg1234567