我有一份家庭作业:
需要实现一个获取INT数组和数字的函数(RotateRight):
int[] res = RotateRight(new int[] { 1, 2, 3, 4, 5, 6 }, 2);
//so then res will be {5,6,1,2,3,4}
并根据给出的数字将所有项目向右旋转后返回数组,在我们的案例2中。
我必须在内存空间方面做到这一点。
我最好的主意是:
如果给出的数字是x,则使用x大小的新int [] tmpArray将所有最后x个项目复制到它。然后使用for循环将int的所有其余部分向右移动。 最后将tmpArray中的项目复制到原始数组的开头。
提前感谢任何建议或帮助
答案 0 :(得分:5)
您可以使用Linq语言的美丽来返回IEnumerable而不处理数组大小:
/// <summary>
/// Get c = a mod (b) with c in [0, b[ like the mathematical definition
/// </summary>
public static int MathMod(int a, int b)
{
int c = ((a % b) + b) % b;
return c;
}
public static IEnumerable<T> ShiftRight<T>(IList<T> values, int shift)
{
for (int index = 0; index < values.Count; index++)
{
yield return values[MathMod(index - shift, values.Count)];
}
}
用法:
[TestMethod]
public void TestMethod1()
{
var res = ShiftRight(new [] { 1, 2, 3, 4, 5, 6 }, 2).ToArray();
Assert.IsTrue(res.SequenceEqual(new[] { 5, 6, 1, 2, 3, 4 }));
}
答案 1 :(得分:1)
大多数内存都没有意义,你可能意味着尽可能少的内存?如果是这样,你应该使用XOR交换数组中的每个项目,即:
var a = 2096;
var b = 842390;
a ^= b;
b ^= a;
a ^= b;
将交换这些数字。
修改强>
完成整个事情的代码:
public static void RotateRight(int[] input, int right)
{
for (var i = 0; i < right; i += 1)
{
RotateRightOne(input);
}
}
public static void RotateRightOne(int[] input)
{
var last = input.Length - 1;
for (var i = 0; i < last; i += 1)
{
input[i] ^= input[last];
input[last] ^= input[i];
input[i] ^= input[last];
}
}
用法:
var arr = new[] {1, 2, 3, 4, 5, 6};
RotateRight(arr, 2);
正如Servy所指出的,这只适用于整数
答案 2 :(得分:0)
不知道C#,但这里有两个C ++版本,第一个(rotate
)通过利用旋转置换的循环结构,第二个(rotate_k
)进行最小可能的元素移动次数( 2*n
)n
只移动一个长度为k
的数组。在两个版本中,使用n - k % n
向右旋转与#include <iostream>
#include <vector>
#include <algorithm>
void
rotate (size_t k, std::vector<int> &a) {
size_t n = a.size();
k = n - k % n;
size_t m = n;
size_t i = 0;
while (m > 0) {
int t = a[i];
size_t j = i;
while (i != (j + k) % n) {
a[j] = a[(j + k) % n];
j = (j + k) % n;
--m;
}
a[j] = t;
--m;
++i;
}
}
void
rotate_k (size_t k, std::vector<int> &a) {
size_t n = a.size();
k = n - k % n;
std::reverse (a.begin(), a.end());
std::reverse (a.begin(), a.begin() + n - k);
std::reverse (a.begin() + n - k, a.end());
}
int
main () {
std::vector<int> a = { 1, 2, 3, 4, 5, 6, 7, 8, 9};
rotate (12, a);
for (auto i : a)
std::cout << i << " ";
std::cout << std::endl;
}
向左旋转相同,因此它们实际上是等效的左旋转。
{{1}}
答案 3 :(得分:0)
你需要在旋转k次后找出每个元素的最终索引,而不是实际旋转k次。 这对我有用:
for(int i=0;i<a.Length;i++){
rotated[(k+i)%(a.Length)]=a[i];
}
答案 4 :(得分:0)
这是一个关于旋转阵列的快速示例A右K步:
var splitPoint=A.Length-(K%A.Length);
var result=new int[A.Length];
int idx=0;
for(var pos=0;pos<A.Length;pos++)
{
if(pos<A.Length-splitPoint)
{
result[pos]=A[splitPoint+pos];
}
else
{
result[pos]=A[idx];
idx++;
}
}
return result;
答案 5 :(得分:0)
C#8现在具有Indices and Ranges
向右旋转...
int[] r = t[1..].Concat(t[0..1]).ToArray();
向左旋转...
int[] r = t[^1..^0].Concat(t[..^1]).ToArray();
代替上面的“ 1”,也可以使用变量:int[] r = t[amt..].Concat(t[0..amt]).ToArray();