编写一个函数,把两个有序向量合并成一个有序向量

  该题目来自于《R语言的科学编程与仿真》的第三章课后练习题的第11题,原题如下:

  编写一个函数把两个有序向量合并成一个有序向量。不要使用sort(x)函数,并尽可能是你的函数有效。也即是,试图使得合并向量需要的运算次数最小。

  函数是不是最有效的暂且不管,先把题目做出来再说。想法是把第二个向量的每个元素依次插入第一个向量,直到第二个向量的元素插入完为止。

  从简单的情况入手,假设向量1为(1,2,3,4),向量2为(0.9,1.5,2,5)。

  对于向量2的第一个元素0.9,为了找到0.9在向量1中的位置,先让向量1中的每个元素减去0.9,即(1-0.9,2-0.9,3-0.9,4-0.9)=(0.1,1.1,2.1,3.1)。这个作差向量的所有元素都大于0,说明0.9比向量1中的任何元素都要小。如果把0.9放进向量1中,那么得到的结果为(0.9,1,2,3,4),0.9的位置为1。

  对于向量2的第二个元素1.5,为了找到1.5在向量1中的位置,先让向量1中的每个元素减去1.5,即(1-1.5,2-1.5,3-1.5,4-1.5)=(-0.5,0.5,1.5,2.5)。这个作差向量的第一个元素小于0,其余都大于0,说明1.5比向量1中的第一个元素要大,比其余元素都要小。如果把1.5放进向量1中,那么得到的结果为(1,1.5,2,3,4),1.5的位置为2。

  对于向量2的第三个元素2,为了找到2在向量1中的位置,先让向量1中的每个元素减去2,即(1-2,2-2,3-2,4-2)=(-1,0,1,2)。这个作差向量的第一个元素小于0,第二个元素等于0,其余都大于0,说,2比向量1中的第一个元素要大,和第二个元素一样大,比其余元素都要小。如果把2放进向量1中,那么得到的结果为(1,2,2,3,4),2的位置可以认为是3。

  对于向量2的第四个元素5,为了找到5在向量1中的位置,先让向量1中的每个元素减去5,即(1-5,2-5,3-5,4-5)=(-4,-3,-2,-1)。这个作差向量的所有元素都小于0,说明5比向量1中的所有元素都要大。如果把5放进向量1中,那么得到的结果为(1,2,3,4,5),5的位置可以认为是5。

  上面的结果是不是存在一个规律呢?答案是肯定的。请看下表。

向量2中的元素 该元素在向量1中的位置 作差向量 作差向量第一个大于0的元素的位置
0.9 1 (0.1,1.1,2.1,3.1) 1
1.5 2 (-0.5,0.5,1.5,2.5) 2
2 3 (-1,0,1,2) 3
5 5 (-4,-3,-2,-1) 没有大于0的元素

除了5这个元素外,向量2中的0.9、1.5、2三个元素在向量1中的位置和“作差向量第一个大于0的元素的位置”保持一致。那为什么5这么特殊呢?答案就是因为5比向量1中的元素都要大,因此5插入向量1中的话,其位置应该是最后,也就是4+1=5。因此,对于最大的元素需要单独处理。

  向量2中的各元素在向量1中的位置都可以用这个规律来找到。向量2中的元素在向量1中的位置可以组成一个位置向量position,即position=(1,2,3,5)。由于要把两个向量合并成一个向量,因此还需要看一下这个位置向量position和向量2的各元素在合并向量中的位置有何关系。

  手动合并向量1和向量2,得到合并向量(0.9,1,1.5,2,2,3,4,5)。向量2中的各元素(也就是0.9、1.5、2、5)在合并向量中的位置依次为1、3、5、8,组成的向量为(1,3,5,8)。那(1,3,5,8)和(1,2,3,5)有什么关系呢?有的,很容易想到的是(1+0,2+1,3+2,5+3)=(1,3,5,8)。而0恰好表示在向量2中0.9前面有0个元素,1恰好表示在向量2中1.5前面有1个元素,2恰好表示在向量2中2前面有2个元素,3恰好表示在向量2中5前面有3个元素。写简明点就是(1,2,3,5)+(0,1,2,3)=(1,3,5,8)。

  知道向量2中的各元素在合并向量中的位置后,那合并向量中的其余位置就是向量1了。由于向量1有顺序,因此直接放就行。

  下面给出R的代码。

h6<-function(vec1,vec2){
n1<-length(vec1)
n2<-length(vec2)
result<-vector(length=n1+n2)#合并向量result
position<-c()
for(i in 1:n2){
  a<-which(vec1-vec2[i]>0)[1]#作差向量中第一个大于0的元素的位置
  if(is.na(a)){locate<-n1+1}else{locate<-a}#这是对最大元素进行单独处理
  position<-c(position,locate)
}
  position<-position+(1:n2)-1
  result[-position]<-vec1#放入向量1
  result[position]<-vec2#放入向量2
  return(result)
}
h6(c(1,2,3,4),c(0.9,1.5,2,5))
#[1] 0.9 1.0 1.5 2.0 2.0 3.0 4.0 5.0
h6(sort(runif(5)),sort(runif(3)))

猜你喜欢

转载自www.cnblogs.com/Enjoy-Respect-9527/p/13202383.html