[英]Java - Rotating array
所以,我们的目标是旋转阵列右侧的元素a
时代。 举个例子; 如果a==2
,则array = {0,1,2,3,4}
将变为array = {3,4,0,1,2}
这是我所拥有的:
for (int x = 0; x <= array.length-1; x++){
array[x+a] = array[x];
}
然而,当[x+a]
大于数组的长度时,这无法解释。 我读到我应该将较大的存储在不同的数组中,但将a
视为变量,我不确定这是最好的解决方案。 提前致谢。
将模数组长度添加到您的代码中:
// create a newArray before of the same size as array
// copy
for(int x = 0; x <= array.length-1; x++){
newArray[(x+a) % array.length ] = array[x];
}
您还应该创建一个要复制到的新Array
,这样您就不会覆盖稍后需要的值。
如果您不想重新发明轮子(也许这是一个练习,但知道它会很好),您可以使用Collections.rotate
。
请注意,它需要一个对象数组,而不是原始数据类型(否则您将在列表中交换数组本身)。
Integer[] arr = {0,1,2,3,4};
Collections.rotate(Arrays.asList(arr), 2);
System.out.println(Arrays.toString(arr)); //[3, 4, 0, 1, 2]
Arraycopy 是一项昂贵的操作,无论是时间还是内存方面。 以下将是一种在不使用额外空间的情况下旋转数组的有效方法(与创建相同大小的新数组的公认答案不同)。
public void rotate(int[] nums, int k) { // k = 2
k %= nums.length;
// {0,1,2,3,4}
reverse(nums, 0, nums.length - 1); // Reverse the whole Array
// {4,3,2,1,0}
reverse(nums, 0, k - 1); // Reverse first part (4,3 -> 3,4)
// {3,4,2,1,0}
reverse(nums, k, nums.length - 1); //Reverse second part (2,1,0 -> 0,1,2)
// {3,4,0,1,2}
}
public void reverse(int[] nums, int start, int end) {
while (start < end) {
int temp = nums[start];
nums[start] = nums[end];
nums[end] = temp;
start++;
end--;
}
}
我认为最快的方法是使用System.arrayCopy()这是本机方法:
int[] tmp = new int[a];
System.arraycopy(array, array.length - a, tmp, 0, a);
System.arraycopy(array, 0, array, a, array.length - a);
System.arraycopy(tmp, 0, array, 0, a);
它还重用现有数组。 在某些情况下它可能是有益的。 最后一个好处是临时数组的大小小于原始数组。 因此,当a
较小时,您可以减少内存使用量。
另一种方法是使用System.arraycopy 进行复制。
int[] temp = new int[array.length];
System.arraycopy(array, 0, temp, a, array.length - a);
System.arraycopy(array, array.length-a, temp, 0, a);
int[] rotate(int[] array, int r) {
final int[] out = new int[array.length];
for (int i = 0; i < array.length; i++) {
out[i] = (i < r - 1) ? array[(i + r) % array.length] : array[(i + r) % array.length];
}
return out;
}
下面的rotate方法将与Collections类的rotate方法与List接口的subList方法结合使用完全相同,即rotate(n,fromIndex,toIndex,dist),其中n是一个整数数组,将给出结果与 Collections.rotate (Arrays.asList (n).subList (fromIndex, toIndex), dist) 相同,其中 n 是整数数组。
首先创建一个交换方法:
public static void swap (int[] n, int i, int j){
int tmp = n[i];
n[i] = n[j];
n[j] = tmp;
}
然后创建旋转方法:
public static void rotate (int[] n, int fromIndex, int toIndex,
int dist){
if(fromIndex > toIndex)
throw new IllegalArgumentException ("fromIndex (" +
fromIndex + ") > toIndex (" + toIndex + ")");
if (fromIndex < toIndex){
int region = toIndex - fromIndex;
int index;
for (int i = 0; i < dist % region + ((dist < 0) ? region : 0);
i++){
index = toIndex - 1;
while (index > fromIndex)
swap (n, index, --index);
}
}
}
问题: https : //www.hackerrank.com/challenges/ctci-array-left-rotation
解决方案:这就是我尝试复杂度为 o(n) 的 arrayLeftRotation 方法的方法
0 到第 k 个索引的第二次
public static int[] arrayLeftRotation(int[] a, int n, int k) {
int[] resultArray = new int[n];
int arrayIndex = 0;
//第一个 nk 个索引将在此循环中填充
for(int i = k ; i resultArray[arrayIndex] = a[i];
数组索引++;
}
// 将在此循环中填充第 2 个索引
for(int j=arrayIndex ; j<(arrayIndex+k); j++){
resultArray[j]=a[j-(nk)];
}
返回结果数组;
}
封装在方法中的 Java 解决方案:
public static int[] rotate(final int[] array, final int rIndex) {
if (array == null || array.length <= 1) {
return new int[0];
}
final int[] result = new int[array.length];
final int arrayLength = array.length;
for (int i = 0; i < arrayLength; i++) {
int nIndex = (i + rIndex) % arrayLength;
result[nIndex] = array[i];
}
return result;
}
对于左旋转它非常简单
取数组长度和要移动的位置数之间的差值。
例如
int k = 2;
int n = 5;
int diff = n - k;
int[] array = {1, 2, 3, 4, 5};
int[] result = new int[array.length];
System.arraycopy(array, 0, result, diff, k);
System.arraycopy(array, k, result, 0, diff);
// 打印输出
package com.array.orderstatistics;
import java.util.Scanner;
public class ArrayRotation {
public static void main(String[] args) {
Scanner scan = new Scanner(System.in);
int n = scan.nextInt();
int r = scan.nextInt();
int[] a = new int[n];
int[] b = new int[n];
for (int i = 0; i < n; i++) {
a[i] = scan.nextInt();
}
scan.close();
if (r % n == 0) {
printOriginalArray(a);
} else {
r = r % n;
for (int i = 0; i < n; i++) {
b[i] = a[(i + r) < n ? (i + r) : ((i + r) - n)];
System.out.print(b[i] + " ");
}
}
}
private static void printOriginalArray(int[] a) {
for (int i = 0; i < a.length; i++) {
System.out.print(a[i] + " ");
}
}
}
在ruby中,可以在一行中旋转一个数组。
def array_rotate(arr)
i, j = arr.length - 1, 0
arr[j],arr[i], i, j = arr[i], arr[j], i - 1, j + 1 while(j<arr.length/2)
puts "#{arr}"
end
问题:给定特定距离旋转数组。 方法 1:将 int 数组转换为 ArrayList。 然后使用 Collections.rotate(list,distance)。
class test1 {
public static void main(String[] args) {
int[] a = { 1, 2, 3, 4, 5, 6 };
List<Integer> list = Arrays.stream(a).boxed().collect(Collectors.toList());
Collections.rotate(list, 3);
System.out.println(list);//[4, 5, 6, 1, 2, 3]
}// main
}
时间复杂度 = O(n)
空间复杂度 = O(1)
该算法从数组的第一个元素 (newValue) 开始,并将其放置在旋转后的位置 (newIndex)。 位于 newIndex 的元素变为 oldValue。 之后,oldValue 和 newValue 被交换。
这个过程重复长度次。
该算法基本上围绕数组反弹,将每个元素放置在新位置。
unsigned int computeIndex(unsigned int len, unsigned int oldIndex, unsigned int times) {
unsigned int rot = times % len;
unsigned int forward = len - rot;
// return (oldIndex + rot) % len; // rotating to the right
return (oldIndex + forward) % len; // rotating to the left
}
void fastArrayRotation(unsigned short *arr, unsigned int len, unsigned int rotation) {
unsigned int times = rotation % len, oldIndex, newIndex, length = len;
unsigned int setIndex = 0;
unsigned short newValue, oldValue, tmp;
if (times == 0) {
return;
}
while (length > 0) {
oldIndex = setIndex;
newValue = arr[oldIndex];
while (1) {
newIndex = computeIndex(len, oldIndex, times);
oldValue = arr[newIndex];
arr[newIndex] = newValue;
length--;
if (newIndex == setIndex) { // if the set has ended (loop detected)
break;
}
tmp = newValue;
newValue = oldValue;
oldValue = tmp;
oldIndex = newIndex;
}
setIndex++;
}
}
以下例程在 java 中旋转数组:
public static int[] rotateArray(int[] array, int k){
int to_move = k % array.length;
if(to_move == 0)
return array;
for(int i=0; i< to_move; i++){
int temp = array[array.length-1];
int j=array.length-1;
while(j > 0){
array[j] = array[--j];
}
array[0] = temp;
}
return array;
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.