*最近在做剑指offer,因为书上都是用c/c++实现的,我又看不懂c++,只能努力试试看用java来实现。*
题目:
有两个已经排好序的数组(假定它们是从小到大排序)A1和A2,请实现一个函数,把A2中的所有数字插入到A1中,并且所有的数字都是排序的。
思路:
因为两个数组都是排好序的,如果我们从前面逐个比较,后面的数字就要不断往后移动,且会重复移动,很明显,这样时间复杂度很大,那么我们从后面往前面比较只要动比较的那个数就好了,前面已经排好序了,就不需要比较了。
1.把数组1的长度扩容到两个数组长度之和。
2.从后往前,比较两个数组,并把大的往扩容后的数组里放(也是从后往前放)。
这是我第一次写的
import java.util.Arrays;
public class InsertArray {
/*
* 需求:有两个排序的数组a1和a2,请实现一个函数,把a2中的所有数字插入到a1中,并且所有的数字是排序的。
* */
public void insertSort(int[] arr1,int [] arr2){
if(arr1!=null && arr2!=null){
int i=arr1.length-1; //记录原数组1的最后一个元素的下表
int newLength=arr1.length+arr2.length;
arr1=Arrays.copyOf(arr1, newLength); //将数组1扩展为长度为两个数组之和。
int j=arr2.length-1; //记录数组2最后一个元素的下标
int k=arr1.length-1; //记录新数组最后一个元素下标。
while(j>=0){ //因为是插入数组2,所以数组2没有遍历完,就要一直循环。
if(arr2[j]>arr1[i]){ //如果数组1元素大于数组2元素,就把数组2元素存放到新数组1里去。
arr1[k--]=arr2[j--];
}else if(arr2[j]==arr1[i]){
arr1[k--]=arr2[j--];
arr1[k--]=arr1[i--];
}else{
arr1[k--]=arr1[i--];
}
}
return arr1;
}else
throw new RuntimeException("传入的数组有误");
}
}
这是测试代码
public class InsertArrayTest {
/**
* @param args
*/
public static void main(String[] args) {
// TODO Auto-generated method stub
int[] arr1={1,2,4,8,19,25};
int[] arr2={3,6,7,12,19,35};
InsertArray iArray=new InsertArray();
iArray.insertSort(arr1, arr2);
for(int x:arr1){
System.out.print(x+",");
}
}
}
测试结果
很遗憾,结果是错的。
我先用myeclipse调试,发觉最后arr1的id在函数执行完之后又回到原来的id,为什么呢?数组作为值传递应该是引用传递,函数内的修改,应该会反馈到函数外。
后来,我想可能copyOf方法的问题,
当我查阅api,原来copyOf是复制了一个新的数组!数组长度是不可变的,我对这句话有了更深的理解,所有的数组扩容都是创立一个新的数组,这里也不例外
我用copyOf创建的新数组虽然把地址赋给了arr1,但是在函数结束后,这个新数组也会消失,arr1重新指向原来的数组。
这是修改后的代码
public class InsertArray {
/*
* 需求:有两个排序的数组a1和a2,请实现一个函数,把a2中的所有数字插入到a1中,并且所有的数字是排序的。
* */
public int[] insertSort(int[] arr1,int [] arr2){
if(arr1!=null && arr2!=null){
int i=arr1.length-1; //记录原数组1的最后一个元素的下表
int newLength=arr1.length+arr2.length;
arr1=Arrays.copyOf(arr1, newLength); //将数组1扩展为长度为两个数组之和。
int j=arr2.length-1; //记录数组2最后一个元素的下标
int k=arr1.length-1; //记录新数组最后一个元素下标。
while(j>=0){ //因为是插入数组2,所以数组2没有遍历完,就要一直循环。
if(arr2[j]>arr1[i]){ //如果数组1元素大于数组2元素,就把数组2元素存放到新数组1里去。
arr1[k--]=arr2[j--];
}else if(arr2[j]==arr1[i]){
arr1[k--]=arr2[j--];
arr1[k--]=arr1[i--];
}else{
arr1[k--]=arr1[i--];
}
}
return arr1;
}else
throw new RuntimeException("传入的数组有误");
}
}
这里我把新创立的数组作为返回值往外传了。这样就可以了。