我正在解决旋转数组并使算法和代码工作的问题
int[] Rotate(int[] ar,int k)
{
if (k <= 0 || k > ar.Length - 1)
return ar;
Reverse(ar, 0, k - 1);
Reverse(ar, k, ar.Length - 1);
Reverse(ar, 0, ar.Length - 1);
return ar;
}
void Reverse(int[] ar,int start, int end)
{
while (start < end)
{
int temp = ar[start];
ar[start] = ar[end];
ar[end] = temp;
start++;
end--;
}
}
现在我想在LINQ中执行此操作并获得以下代码,我认为这可以做得更好。
int[] Rotate(int[] ar,int k)
{
if (k <= 0 || k > ar.Length - 1)
return ar;
int[] ar1=ar.Take(k-1).Reverse().ToArray();
int[] ar2=ar.Skip(k - 1).Take(ar.Length - k+1).Reverse().ToArray();
int[] ar3 = ar1.Concat(ar2).Reverse().ToArray();
return ar3;
}
这是编程珍珠的一个众所周知的算法 - http://books.google.com/books?id=kse_7qbWbjsC&lpg=PA14&ots=DfzTzQCSar&dq=rotate%20an%20array%20programming%20pearls&pg=PA14#v=onepage&q&f=false
一般来说如何开发我的LINQ技能,如果我遇到编程问题,现在我只考虑for循环或foreach循环,如何考虑linq运算符。我正在阅读C#4.0简介,除了练习任何建议?
答案 0 :(得分:14)
说实话,我不确定为什么你会得到所有的逆转。怎么样:
int[] Rotate(int[] ar,int k)
{
if (k <= 0 || k > ar.Length - 1)
return ar;
return ar.Skip(k) // Start with the last elements
.Concat(ar.Take(k)) // Then the first elements
.ToArray(); // Then make it an array
}
这是一个简短但完整的程序来演示它:
using System;
using System.Linq;
class Test
{
static int[] Rotate(int[] ar,int k)
{
if (k <= 0 || k > ar.Length - 1)
return ar;
return ar.Skip(k) // Start with the last elements
.Concat(ar.Take(k)) // Then the first elements
.ToArray(); // Then make it an array
}
static void Main()
{
int[] values = { 1, 2, 3, 4, 5 };
int[] rotated = Rotate(values, 3);
Console.WriteLine(string.Join(", ", rotated));
}
}
输出:4,5,1,2,3
编辑:我刚刚注意到我的代码和原始代码之间存在一个主要区别:你的代码修改了原始数组 - 我的返回带有旋转值的 new 数组。您的LINQ代码也是如此,但这意味着如果您使用仅查看原始数组的内容测试我的代码,您将看不到旋转。
LINQ旨在通常以这种方式工作 - 它有利于返回新序列而不是修改现有序列。
答案 1 :(得分:3)
从您的代码开始:
int[] ar1=ar.Take(k-1).Reverse().ToArray();
int[] ar2=ar.Skip(k - 1).Take(ar.Length - k+1).Reverse().ToArray();
int[] ar3 = ar1.Concat(ar2).Reverse().ToArray();
由于您只想获得所有剩余的元素,因此不需要第二行中的Take。
ar1和ar2只是枚举,所以它们不需要是数组。不需要ToArray调用。通过一些创意重命名,我们有:
IEnumerable<int> revFirst = ar.Take(k-1).Reverse();
IEnumerable<int> revLast = ar.Skip(k-1).Reverse();
int[] ar3 = revFirst.Concat(revLast).Reverse().ToArray();
现在我们有了
rev(rev(first)+ rev(last))
分发外部转速
rev(rev(last))+ rev(rev(first))
与
相同last + first
将相同的操作应用于代码
IEnumerable<int> first = ar.Take(k-1);
IEnumerable<int> last = ar.Skip(k-1);
int[] ar3 = last.Concat(first).ToArray();
进一步简化为
int[] ar3 = ar.Skip(k-1).Concat(ar.Take(k-1)).ToArray();
现在我们有Jon Skeet的答案,所以我们必须完成。
答案 2 :(得分:-1)
这是我的解决方法
public int[] solution(int[] A, int K) {
// write your code in C# 6.0 with .NET 4.5 (Mono)
if (A.Length <= 1)
{
return A;
}
var rotate = K % A.Length;
var leftSide = A.Length - rotate;
var arr1 = A.AsParallel().Skip(leftSide).Take(rotate);
var arr2 = A.AsParallel().Take(leftSide);
return arr1.Concat(arr2).ToArray();
}
您可以检查我的github。我还针对其他情况以及其他合规性课程和挑战进行了一些单元测试