在c#中向右旋转一个int数组?

时间:2013-11-12 15:58:38

标签: c# .net arrays algorithm

我有一份家庭作业:

需要实现一个获取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中的项目复制到原始数组的开头。

提前感谢任何建议或帮助

6 个答案:

答案 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*nn只移动一个长度为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();