今天,我遇到了一个让我感到困惑的问题
问题
我有一个数组:arr[a1, a2, a3....an, b1, b2, b3.....bn]
,如何移动数组的元素以将其转移到arr[a1, b1, a2, b2......an,bn]
,你应该就地移动(space complexity should be constant
)。
我尽力将其考虑在内并得到一个丑陋的算法,就像冒泡一样:
b1 moves forward by n - 1;
b2 moves forward by n - 2;
.
.
bn-1 moves forward by 1;
但时间复杂度是O(n 2 ),谁可以给我一个更好的算法? 我找到了另一种更好的方法,就像快速排序:
First we swap the element from a(n/2) to a(n) with the elements from b1 to b(n/2);now we get two independent sub problems,So we can solve it by recursion.
T(n) = 2T(n/2) + O(n)
the time complexity is O(nlgn)
这里是整个代码:
void swapArray(int *arr, int left, int right)
{
int mid = (left + right) >> 1;
int temp = mid + 1;
while(left <= mid)
{
swap(arr[left++], arr[temp++]);
}
}
void arrayMove(int *arr, int lb, int le, int rb, int re)
{
if(le - lb <= 0 || re - rb <= 0)
return;
int mid = (lb + le + 1) >> 1;
int len = le - mid;
if(rb + len >= re)
{
swapArray(arr, mid + 1, rb);
}
else
{
swapArray(arr, mid, rb + len);
}
arrayMove(arr, lb, mid - 1, mid, le);
arrayMove(arr, rb, rb + len, rb + 1 + len, re);
}
答案 0 :(得分:1)
在涉足和试验/磕磕绊绊之后,我想我已经开始明白了,虽然数学对我来说仍然很难。我认为它是这样的:
确定转置的置换周期(这可以在实际数据传输期间或之前完成)。公式to = 2*from mod (M*N - 1), where M = 2, N = array length / 2
可用于查找索引目标(置换)。 (我减少了这个问题的公式,因为我们知道M = 2.)访问索引的标记可以帮助确定下一个循环的开始(从技术上讲,可以使用循环计算而不是位集作为标记,仅保留下一个循环 - 从内存开始)。临时变量将数据从起始地址保存到循环结束。
总而言之,这可能意味着两个临时变量,循环计算,以及每个数组元素就地移动一个。
例如:
arr = 0,1,2,3,4,5,6,7,8,9
destinations: 0,2,4,6,8,1,3,5,7,9
start = 1, tmp = arr[1]
cycle start
5->1, 7->5, 8->7, 4->8, 2->4, tmp->2
cycle end
not visited - 3
start = 3, tmp = arr[3]
cycle start
6->3, tmp->6
cycle end
Transposition complete.
有问题吗?
请随意询问,请访问http://en.wikipedia.org/wiki/In-place_matrix_transposition
答案 1 :(得分:0)
这是Python中的一个简短代码:
n = 4
a = ['a1', 'a2', 'a3', 'a4', 'b1', 'b2', 'b3', 'b4']
result = a[:n]
for index in range(n):
result.insert(index*2 + 1, a[n+index])
print result # prints ['a1', 'b1', 'a2', 'b2', 'a3', 'b3', 'a4', 'b4']
答案 2 :(得分:0)
也许这不是最好的方式,因为它不直接回答你的问题,但你为什么不简单地将元素的新索引映射到元素的旧索引?
old_array: [a1, a2, a3....an, b1, b2, b3.....bn]
=>
lookup: [0 n 1 n+1 2 n+2 ... n-1 2n-1]
=>
[a1 b1 a2 b2 ... an bn]
如果要从索引中抓取元素
Get(index)
return old_array[lookup[index]]
End
Get(2) => old_array[lookup[2]] => old_array[1] => a2 | a2 is at index 2
答案 3 :(得分:0)
使用Java代码&#34;数组从a1,..,an,b1,..,bn移动到a1,b1,..,an,bn&#34;
private static void myTrans(int[] m) {
int n = (m.length - 1);
int i = 1;
for (int start = 1; start < n; start++) {
int temp = m[start];
m[start] = m[n / 2 + i];
for (int j = (n / 2 + i); j > start; j--) {
m[j] = m[j - 1];
}
start++;
m[start] = temp;
printArray(m);
i++;
}
}
答案 4 :(得分:0)
public void shuffle(char[] arr, int left, int right){
//center
int c = (left+right)/2;
int q = 1 + (left+c)/2;
for(int k=1,i=q;i<=c;i++,k++){
//Swap elements
int temp = arr[i];
arr[i] = arr[c+k];
arr[c+k] = temp;
}
shuffle(arr,left,c);
shuffle(arr,c+1,right);
}
这将在中心附近洗牌:
此解决方案的复杂性将为nlogn
答案 5 :(得分:0)
请检查我在Java中进行就地排序的尝试解决方案:
时间复杂度:O(N),其中N是数组的长度。 空间复杂度:O(1)
public static void sortSpecialArray(String[] array) {
sortSpecialArrayUtil(array);
sortSpecialArrayUtil(array);
}
/**
* Given an array with ['a1', 'a2', 'a3', ..., 'aN', 'b1', 'b2', 'b3', ...,'bN', 'c1'...'cN']
* sort the array to be a1, b1, c1...
*
* O(N) time complexity (derived from O(N * K) below)
* O(1) space complexity
*/
private static void sortSpecialArrayUtil(String[] array) {
// O(1) space complexity requires this function to sort the array in-place
// this can be done using a pointer that keeps track of where we are
// in the array. The idea is to swap the values in the array to get the element in the right place.
int n = stripNumber(array[array.length - 1]);
int charCount = array.length / n;
// start the loop at index = 1, up until index = array.length - 2
// ignore those two elements because they're already in the right place
int lastIndex = array.length - 2;
String element;
for (int i = 1; i <= lastIndex; i++) {
element = array[i];
swap(array, i, getCorrectIndex(charCount, element));
}
}
/**
* Assume that array's element is in format of something like "a1", where there can only be one 'letter' before the number
* extract number from the string
*
* This is done in time O(K), where K is the length of the String
*/
private static int stripNumber(String str) {
return Integer.parseInt(str.substring(1, str.length()));
}
private static int getCorrectIndex(int charCount, String element) {
char c = Character.toLowerCase(element.charAt(0));
int num = stripNumber(element);
// the correct index is found by the following formula: index = charDistance + (charCount * (num - 1))
int charDistance = c - 'a';
return charDistance + (charCount * (num - 1));
}
private static void swap(String[] array, int fromIndex, int toIndex) {
String temp = array[toIndex];
array[toIndex] = array[fromIndex];
array[fromIndex] = temp;
}
测试:
@Test
public void testSortArray() {
String[] testCase = new String[] { "a1", "a2", "a3", "a4", "a5", "b1", "b2", "b3", "b4", "b5", "c1", "c2", "c3", "c4", "c5", "d1", "d2", "d3", "d4", "d5" };
sortSpecialArray(testCase);
for (String s : testCase) {
System.out.print(s + " ");
}
}
答案 6 :(得分:-2)
假设输入数组以 [a1,a2,a3,b1,b2,b3,c1,c2,c3] 给出,因此我们希望输出为 [A1,B1,C1,A2,B2,C2,A3,B3,C3] 即可。让我将数组表示为2D矩阵 每行表示组大小为n(在这种情况下n为3)。
Original array
a1 a2 a3
b1 b2 b3
c1 c2 c3
What we Want
a1 b1 c1
a2 b2 c2
a3 b3 c3
你注意到了什么。让我告诉你输出数组实际上是转置的输入数组表示为2D矩阵,可以使用常量空间轻松完成。
实施Code