问题:将一个n元一维向量向左旋转i个位置。如,当n=8且i=3时,向量abcdefgh旋转为defghabc.求解决方案。
1. 首先将x的前i个元素复制到一个临时数组中,然后将余下的n-i个元素向左移动i个位置,最后将最初的i个元素从临时数组中复制到x中余下的位置。但是,这种办法使用的i个额外位置产生了过大的存储空间消耗。
2. 定义一个函数将x向左旋转一个位置然后调用该函数i次。但该方法又产生了过多的运行时间消耗。
3. 要在有限的资源内解决该问题,显然需要更复杂的程序。有一个成功的方法有点像精巧的杂技动作:移动x[0]到临时变量t,然后移动x[i]至x[0],x[2i]至x[i],依次类推(将x中的所有下标对n取模),直至返回到取x[0]中的元素,此时改为从t取值然后终止过程。
4. 我们将问题看成把数组ab转换成ba,同时假定我们拥有一个函数可以将数组中的特定部分元素求逆。从ab开始,先对a求逆,得到ar b,然后对b求逆,得到ar br ,然后整体求逆,得到(ar b r)r 。此时就是ba。
杂技算法的代码:
package bczj.chapter2;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import com.util.MyList;
/**
*
*
* Title:杂技算法 <br>
* Description: <br>
* Copyright: Copyright (c) 2007<br>
* Company:xx有限公司<br>*
* @author yingkh
* @version 1.0
* @date 2010-8-3
*/
public class Acrobatics {
public Acrobatics(){
}
public List<String> rotation(List<String> list, int rotdist) {
//最大公约数(Greatest common divisor)
int m = gcd (rotdist,list.size());
int j = 0;
for(int i=0; i<m; i++) {
String temp = list.get(i);
j = i;
while(true) {
int k = j + rotdist;
if(k >= list.size()) {
k -= list.size();
}
if( k== i) {
break;
}
list.set(j, list.get(k));
j = k;
}
list.set(j, temp);
}
return list;
}
//求最大公约数
private int gcd(int i, int j) {
while(i != j) {
if(i > j){
i -= j;
}else {
j -= i;
}
}
return i;
}
/**
* @param args
*/
public static void main(String[] args) {
Acrobatics ac = new Acrobatics();
MyList myList = new MyList();
List list = myList.createStringList(6);
List result = ac.rotation(list, 3);
myList.print(result);
}
}
/*
* 编程珠玑:将一个n元一维向量向左旋转i个位置。如当n=8,i=3时,向量abcdefgh旋转为
* defghabc.
*
* */
|
旋转算法:
package bczj.chapter2;
import java.util.Collections;
import java.util.List;
import com.util.MyList;
/**
*
*
* Title:翻转数组 <br>
* Description: <br>
* Copyright: Copyright (c) 2007<br>
* Company:XX限公司<br> *
* @author yingkh
* @version 1.0
* @date 2010-8-3
*/
public class InverseArray {
public InverseArray() {
}
//翻转元素
private List<String> reverseList(List<String> list, int begin, int end) {
if(begin <= end) {
for(int i = begin; i < end; i++,end--) {
if(i<end-1) {
String temp = list.get(i);
list.set(i, list.get(end-1));
list.set(end-1, temp);
}
}
}
return list;
}
/**
* @param args
*/
public static void main(String[] args) {
Acrobatics ac = new Acrobatics();
MyList myList = new MyList();
List list = myList.createStringList(10);
InverseArray inverseArray = new InverseArray();
inverseArray.reverseList(list, 0, 5);
inverseArray.reverseList(list, 5, 10);
inverseArray.reverseList(list, 0, 10);
myList.print(list);*/
}
}
|
公用的myList类:
package com.util;
import java.util.ArrayList;
import java.util.List;
public class MyList {
public MyList() {
}
//产生String类型的list
public List<String> createStringList(int length) {
List<String> list = new ArrayList<String>();
for(int i=0; i<length ;i++){
list.add(String.valueOf(i));
}
return list;
}
//打印list
public void print(List<String> list) {
for(int i=0; i<list.size() ;i++) {
System.out.println("第"+i+"个元素为: "+list.get(i));
}
}
}
|
其实Collection中已经有这个算法了,Collections.rotate()方法。
rotate
public static void rotate(List<?> list,int distance)根据指定的距离轮换指定列表中的元素。调用此方法后,对于 0 和 list.size()-1(包括)之间的所有 i 值,索引 i 处的元素将是以前位于索引 (i - distance) mod list.size() 处的元素。(此方法对列表的大小没有任何影响。) 例如,假设 list 包含 [t, a, n, k, s]。在调用 Collections.rotate(list, 1)(或 llections.rotate(list, -4))之后,list 将包含 [s, t, a, n, k]。 注意,此方法用于子列表时非常有用,可以在保留其余元素顺序的同时,在列表中移动一个或多个元素。例如,以下语句可以将索引 j 处的元素向前移动到位置 k 上(k 必须大于等于 j): Collections.rotate(list.subList(j, k+1), -1);为了具体说明这一点,假设 list 包含 [a, b, c, d, e]。要将索引 1 处的元素(b)向前移动两个位置,请执行以下调用: Collections.rotate(l.subList(1, 4), -1); 得到的列表是 [a, c, d, b, e]。
我们来看一下它的源码吧:
private static final int ROTATE_THRESHOLD = 100;
public static void rotate(List<?> list, int distance) {
if (list instanceof RandomAccess || list.size() < ROTATE_THRESHOLD)
rotate1((List)list, distance);
else
rotate2((List)list, distance);
}
private static <T> void rotate1(List<T> list, int distance) {
int size = list.size();
if (size == 0)
return;
distance = distance % size;
if (distance < 0)
distance += size;
if (distance == 0)
return;
for (int cycleStart = 0, nMoved = 0; nMoved != size; cycleStart++) {
T displaced = list.get(cycleStart);
int i = cycleStart;
do {
i += distance;
if (i >= size)
i -= size;
displaced = list.set(i, displaced);
nMoved ++;
} while(i != cycleStart);
}
}
private static void rotate2(List<?> list, int distance) {
int size = list.size();
if (size == 0)
return;
int mid = -distance % size;
if (mid < 0)
mid += size;
if (mid == 0)
return;
reverse(list.subList(0, mid));
reverse(list.subList(mid, size));
reverse(list);
}
|
很有趣,当list的长度小于100时,list默认用的是杂技算法,否则用的是翻转算法。
另外我们看一下list的reverse方法,写的很精妙:
public static void reverse(List<?> list) {
int size = list.size();
if (size < REVERSE_THRESHOLD || list instanceof RandomAccess) {
for (int i=0, mid=size>>1, j=size-1; i<mid; i++, j--)
swap(list, i, j);
} else {
ListIterator fwd = list.listIterator();
ListIterator rev = list.listIterator(size);
for (int i=0, mid=list.size()>>1; i<mid; i++) {
Object tmp = fwd.next();
fwd.set(rev.previous());
rev.set(tmp);
}
}
}
|
同样,swap方法:
public static void swap(List<?> list, int i, int j) {
final List l = list;
l.set(i, l.set(j, l.get(i)));
}
|
ArrayList的set方法:
public E set(int index, E element) {
RangeCheck(index);
E oldValue = (E) elementData[index];
elementData[index] = element;
return oldValue;
}
|
不得不感叹java的源码,确实精妙。
分享到:
相关推荐
在编程世界中,"编程珠玑"通常指的是那些巧妙、高效且优雅的编程技巧和算法。这个名为"bianchengzhuji.rar_bianchengzhuji"的压缩包似乎包含了与编程技巧相关的资源,特别是从描述中我们可以看到一个有趣的问题:...
王争的算法课堂 # Title Languages 题型 纯编程题 第一讲:纯编程题 [1108. IP 地址无效化(简单)][] [344. 反转字符串(简单)][] [剑指 Offer 58 - I. 翻转单词顺序(简单)][] [剑指 Offer...
内容概要:本文深入剖析了安川MP7系列工业控制系统的关键源码,重点介绍了运动轨迹规划、通信协议处理以及故障处理机制等方面的技术细节。通过对实际代码片段的解读,揭示了该系统在硬件寄存器直接访问、特殊功能码处理等方面的独特之处。同时,文中还分享了一些基于实践经验得出的重要参数设置及其背后的故事,如特定摩擦补偿系数的选择原因等。 适合人群:从事工业自动化领域的工程师和技术人员,尤其是对安川产品有一定了解并希望深入了解其内部工作机制的专业人士。 使用场景及目标:帮助读者掌握安川MP7系列控制器的工作原理,提高对类似系统的维护能力和故障排查效率。对于想要进一步研究或二次开发该系统的开发者来说,也能提供宝贵的参考资料。 其他说明:文章不仅限于理论讲解,还包括了许多来自一线的实际案例和经验教训,使读者能够更好地理解和应用所学知识。
自动化测试与脚本开发_Python3_pynput_键盘鼠标操作录制执行代码生成工具_用于自动化测试_脚本录制_重复操作模拟_宏命令生成_提高工作效率_支持GUI界面_跨平台兼容_
嵌入式八股文面试题库资料知识宝典-深入分析Windows和Linux动态库应用异同.zip
嵌入式八股文面试题库资料知识宝典-C语言总结.zip
内容概要:本文详细探讨了风储直流微电网中母线电压控制的关键技术。首先介绍了风储直流微电网的背景和发展现状,强调了母线电压控制的重要性。接着阐述了永磁风机储能并网技术,解释了永磁风机如何通过直接驱动发电机将风能转化为电能,并确保与电网的同步性和稳定性。然后深入讨论了双闭环控制MPPT技术,这是一种通过内外两个闭环控制系统来实现实时调整发电机运行参数的技术,确保风机始终处于最大功率点附近。最后,文章探讨了储能控制母线电压平衡的方法,即通过储能系统的充放电操作来维持母线电压的稳定。结论部分指出,通过这些技术的有机结合,可以实现对风储直流微电网的有效管理和优化控制。 适合人群:从事新能源技术研发的专业人士、电气工程研究人员、风电系统工程师。 使用场景及目标:适用于希望深入了解风储直流微电网母线电压控制策略的研究人员和技术人员,旨在帮助他们掌握最新的控制技术和方法,以提高系统的稳定性和效率。 其他说明:文章还对未来风储直流微电网的发展进行了展望,指出了智能化和自动化的趋势,以及储能技术的进步对系统性能的影响。
嵌入式八股文面试题库资料知识宝典-C++object-oriented.zip
内容概要:文章详细介绍了HarmonyOS的目录结构及其重要性,从整体框架到核心目录的具体功能进行了全面剖析。HarmonyOS凭借其分布式架构和跨设备协同能力迅速崛起,成为全球操作系统领域的重要力量。文章首先概述了HarmonyOS的背景和发展现状,强调了目录结构对开发的重要性。接着,具体介绍了根目录文件、AppScope、entry和oh_modules等核心目录的功能和作用。例如,AppScope作为全局资源配置中心,存放应用级的配置文件和公共资源;entry目录是应用的核心入口,负责源代码和界面开发。此外,文章还对比了HarmonyOS与Android、iOS目录结构的异同,突出了HarmonyOS的独特优势。最后,通过旅游应用和电商应用的实际案例,展示了HarmonyOS目录结构在资源管理和代码组织方面的应用效果。; 适合人群:具备一定编程基础,尤其是对移动操作系统开发感兴趣的开发者,包括初学者和有一定经验的研发人员。; 使用场景及目标:①帮助开发者快速理解HarmonyOS的目录结构,提高开发效率;②为跨设备应用开发提供理论和技术支持;③通过实际案例学习资源管理和代码组织的最佳实践。; 其他说明:HarmonyOS的目录结构设计简洁明了,模块职责划分明确,有助于开发者更好地管理和组织代码和资源。随着万物互联时代的到来,HarmonyOS有望在开发便利性和生态建设方面取得更大进展,吸引更多开发者加入其生态系统。
内容概要:本文详细介绍了飞轮储能充放电控制的Simulink仿真模型,重点在于采用永磁同步电机的矢量控制和dq轴解耦控制策略。充电时,外环控制转速,内环控制dq轴电流;放电时,外环控制直流母线电压,内环同样控制dq轴电流。文中还讨论了硬件与软件环境的选择,以及仿真模型的调试与运行情况,最终得出该模型具有良好的跟随性能和波形完美度。 适用人群:从事电力电子系统、储能技术和Simulink仿真的研究人员和技术人员。 使用场景及目标:适用于需要对飞轮储能系统进行深入研究和仿真的场合,旨在提高充放电效率和稳定性,满足不同应用场景的需求。 其他说明:该仿真模型已调试完成,可以直接用于进一步的研究和实际应用,为未来的飞轮储能技术研发提供了有价值的参考。
嵌入式八股文面试题库资料知识宝典-北京瑞德方科技.zip
嵌入式八股文面试题库资料知识宝典-同方万维硬件测试工程师.zip
1_15套python PDF格式.zip
内容概要:本文详细介绍了三相三电平整流器的仿真过程及其性能分析。文中首先概述了三相三电平整流器的基本概念及其在电力系统中的重要作用,接着重点探讨了电压电流双闭环控制方式的工作原理和优势,以及SPWM调制技术的具体应用。通过仿真文件展示了整流器在不同条件下的响应情况,验证了这两种技术的有效性和优越性。最后,作者表达了对未来实际应用的期望。 适合人群:从事电力电子研究的技术人员、高校相关专业师生、对电力控制系统感兴趣的工程爱好者。 使用场景及目标:适用于希望深入了解三相三电平整流器工作原理和技术细节的研究人员;目标是在理论基础上掌握电压电流双闭环控制和SPWM调制的实际应用方法。 其他说明:本文提供的仅为仿真文件,未涉及实物实验数据。
嵌入式八股文面试题库资料知识宝典-恒光科技.zip
嵌入式八股文面试题库资料知识宝典-北京天华威视科技有限公司面试题.zip
嵌入式八股文面试题库资料知识宝典-微软研究院笔试题目的答案.zip
Arduino UART实验例程,开发板:正点原子EPS32S3,本人主页有详细实验说明可供参考。
嵌入式八股文面试题库资料知识宝典-朝歌数码.zip
嵌入式八股文面试题库资料知识宝典-Cortex系列.zip