数组元素整体移动问题的研究

问题介绍

有一类问题是,将数组进行整体平移,例如整体向左或向右平移3个长度,类似于这类问题的解决方案很多,下面就来尝试使用Java语言给出三种解决方法,设想问题是将一个数组整体向右平移k个单位,即若平移前数组为{1,2,3,4,5,6,7},平移3个长度后数组为{5,6,7,1,2,3,4}。

朴素思想

一般,最朴素的方法是先创建一个新数组,然后按规律将数组一一赋值即可。如下代码所示:

/**
	 * 最朴素的算法,开辟另一个数字,拷贝进去就是了
	 * @param a 输入数组
	 * @param k 移动步数
	 * 时间复杂度 O(N)
	 * 空间复杂度 O(N)
	 */
	public static void rotate1(int[] a,int k) {
		int[] b = new int[a.length];
		for(int i=0;i<k;i++) {
			b[i]=a[a.length-k+i];
		}
		for(int j=0;j<a.length-k;j++) {
			b[j+k]=a[j];
		}
		System.arraycopy(b, 0, a, 0, a.length);
	}

这种方法的时间复杂度为O(N),空间复杂度也为O(N),也是我们最常想到的方法。

冒泡思想

回想起我之前学习的冒泡排序算法的思想,感觉这问题有点像,例如5,6,7依次向上冒泡,1,2,3,4依次沉到底部,因此,我们可以借助冒泡排序的思想来解决这个问题。如下代码所示:

/**
	 * 想到冒泡排序算法的思想
	 * @param a 输入数组
	 * @param k 移动步数
	 * 时间复杂度 O(N*k)
	 * 空间复杂度 O(1)
	 */
	public static void rotate2(int[] a,int k) {
		for(int i=0;i<k;i++) {
			for(int j=a.length-k+i;j>i;j--) {
				int tmp=a[j];
				a[j]=a[j-1];
				a[j-1]=tmp;
			}
		}
	}

这种方法的时间复杂度为O(N*k),空间复杂度为O(1),借助了冒泡排序的思想。

旋转思想

仔细研究变化前后的数组我们会发现,首先将数组分解成两部分,然后分别对两部分进行旋转颠倒,最后合并成大数组再旋转一次,即可完成。如下代码所示:

/**
	 *
	 * @param a 输入数组
	 * @param k 移动步数
	 * 时间复杂度 O(N)
	 * 空间复杂度 O(1)
	 */
	public static void rotate3(int[] a,int k) {
		reverse(a,0,a.length-k-1);
		reverse(a,a.length-k,a.length-1);
		reverse(a,0,a.length-1);
	}

	public static void reverse(int[]a,int start,int end) {
		for(int i=0;i<(end-start+1)/2;i++) {
			int tmp=a[start+i];
			a[start+i]=a[end-i];
			a[end-i]=tmp;
		}
	}

这种方法的时间复杂度为O(N),空间复杂度为O(1),借助了旋转的思想,比较巧妙。

时间: 2024-10-12 17:09:01

数组元素整体移动问题的研究的相关文章

数组元素的左右旋转

我们定义一组数组元素,例如:1 2 3 4 5 6 右旋一位:2 3 4 5 6 1 左旋一位:6 1 2 3 4 5 如果右旋一位,我们会想到把数组元素整体右旋一位,本来的首元素放到最后一位,之后的每一位都向左移动一位.我们可以先把首元素取出标记一下tmp=arr[0],之后的每一位都向前移动一位,arr[i-]=arr[i],最后把tmp放到最后一位. 同理,右旋n位与右旋一位原理相同,不同的就是在一个循环中每旋一次,n--,直到为零. 代码: #include <stdio.h> voi

javascript 常见数组操作( 1、数组整体元素修改 2、 数组筛选 3、jquery 元素转数组 4、获取两个数组中相同部分或者不同部分 5、数组去重并倒序排序 6、数组排序 7、数组截取slice 8、数组插入、删除splice(需明确位置) 9、数组遍历 10、jQuery根据元素值删除数组元素的方)

主要内容: 1.数组整体元素修改 2. 数组筛选 3.jquery 元素转数组 4.获取两个数组中相同部分或者不同部分 5.数组去重并倒序排序 6.数组排序 7.数组截取slice 8.数组插入.删除splice(需明确位置) 9.数组遍历 10.jQuery根据元素值删除数组元素的方法 数组常见操作包含了 增.删.查.改.插入.交集.并集 1.数组整体元素修改 //map,给数组每个元素加1 输出[1,2,3] $.map([0,1,2],function(n){ return n+1; })

1008. 数组元素循环右移问题 (20)

1008. 数组元素循环右移问题 (20) 一个数组A中存有N(N>0)个整数,在不允许使用另外数组的前提下,将每个整数循环向右移M(M>=0)个位置,即将A中的数据由(A0 A1--AN-1)变换为(AN-M -- AN-1 A0 A1--AN-M-1)(最后M个数循环移至最前面的M个位置).如果需要考虑程序移动数据的次数尽量少,要如何设计移动的方法? 输入格式:每个输入包含一个测试用例,第1行输入N ( 1<=N<=100).M(M>=0):第2行输入N个整数,之间用空格

数组元素循环右移

/*1008. 数组元素循环右移问题 (20) 时间限制 400 ms 内存限制 65536 kB 代码长度限制 8000 B 判题程序 Standard 一个数组A中存有N(N>0)个整数,在不允许使用另外数组的前提下,将每个整数循环向右移M(M>=0)个位置,即将A中的数据由(A0 A1--AN-1)变换为(AN-M -- AN-1 A0 A1--AN-M-1)(最后M个数循环移至最前面的M个位置).如果需要考虑程序移动数据的次数尽量少,要如何设计移动的方法?   输入格式:每个输入包含一

PAT 乙级 1008 数组元素循环右移问题 (20) C++版

1008. 数组元素循环右移问题 (20) 时间限制 400 ms 内存限制 65536 kB 代码长度限制 8000 B 判题程序 Standard 一个数组A中存有N(N>0)个整数,在不允许使用另外数组的前提下,将每个整数循环向右移M(M>=0)个位置,即将A中的数据由(A0A1--AN-1)变换为(AN-M -- AN-1 A0 A1--AN-M-1)(最后M个数循环移至最前面的M个位置).如果需要考虑程序移动数据的次数尽量少,要如何设计移动的方法? 输入格式:每个输入包含一个测试用例

【PAT】B1008 数组元素循环右移问题

猥琐方法 直接分成两部分输出数组元素,注意空格的问题 #include<stdio.h> int arr[101]; void Priarr(int a,int b){ if(a<=b) for(int i=a;i<=b;i++){ if(i!=a)printf(" "); printf("%d",arr[i]); } } int main(){ int N,M; scanf("%d%d",&N,&M);

453. 最小移动次数使数组元素相等(数学)

题意:一次操作,n元数组中任意n-1个数+1.求取最小操作次数使得数组所有元素相等. 分析: 1.正面思考,每次将数组中除最大值以外的所有值+1,直到所有元素都相等. 2.反面思考,每次将数组中的最大值-1,直到所有元素相等(最少操作次数=数组和-n*数组最小值) n元数组,其中n-1元+1,因为只要求元素相等,可以不考虑值,可以整体再-1,两次操作后也就是一元-1. 反面思考数学证明: 假设所有元素都相等时数字为k, 如果最小数字经过x次移动能够等于k, 则此时所有元素也能等于k, 此时移动次

js删除数组元素中的指定值

js删除数组元素中的指定值:所谓删除数组元素中指定的值,就是删除具有指定的数组项,下面就通过实例代码代码介绍一下如何实现此功能.代码如下: var theArray=["蚂蚁部落",2,"青岛市南区","antzone","蚂蚁部落"]; for(var i=0;i<theArray.length;i++){ if(theArray[i]=="蚂蚁部落"){ theArray.splice(i,1);

用指针引用数组元素并打印输出

<span style="font-size:18px;">#include<stdio.h> void main() { int a[3][4]={{1,2,3,4},{5,6,7,8},{9,10,11,12}}; int (*p)[4];//数组指针变量声明 int row,col; p=a;//指针p指向数组元素为4的数组 //打印输出数组指针p指向的数组的值 for(row=0;row<3;row++) { for(col=0;col<4;