行道树种黑松间距多少米一棵?

小说:行道树种黑松间距多少米一棵?作者:扁丁开建更新时间:2019-04-19字数:95966

林珂点了点头,打趣道:“怎么?他在你面前一点也不动心,是不是你的魅力不足,或者说他那里有点问题。”

黑龙江日本海棠都在哪里买?

叶扬点了点头,双眼泛着泪光,紧紧的攥着孙艺维的手说道:“你回来了”。
大将得到恶魔果树能发挥的每一颗恶魔果实的力量都等同于每一颗恶魔果实都开发到大将层次的地步,我这么说你们都应该明白,只要你的实力有四皇那么强,那么每一颗恶魔果实的力量都等同于一尊四皇强者吃下那一颗恶魔果实之后开发到四皇层次所能发挥的力量。

他在一家名为斗奶,哦不,是斗游的网站,直播一款名叫“撸断肠”,哦不,是“ldc”的竞技游戏。

前面两篇总结了常见的几种排序算法的主要思想以及C++与python两种方式的实现过程, 几种排序算法中比较重要的就是归并排序和快速排序,这两种方法的相同点就是都使用了分治的思想,现在用来解决两个具体问题。

1.分治法

  分治法就是将原问题分割成同等结构的子问题,之后将子问题逐一解决后,原问题也就得到了解决。 需要注意的是归并排序和快速排序虽然都使用了分治的思想,但它们分别代表了分治算法的两类基本思想。对于归并排序而言,它对“分”这个过程没有做太多操作,只是简单的将数组分为两部分然后递归的进行归并排序,而归并排序的关键是这样分完之后如何将它们归并起来,即merge()操作。 
  而对于快速排序来说,则是废了很大功夫放在了如何“分”这个问题上,我们是选取了一个标定点,然后使用partition()这个子过程将这个标定点移到了合适的位置,当它移到了合适的位置之后才将整个数组分成了两部分,而这样分完之后,在“合”的时候就不用做过多的考虑了,只需要一步一步递归下去就好了。 
  下面解决两个直接从归并排序和快速排序中衍生出来的具体问题的。

2.求逆序对数量

  • 问题描述:在数组中的两个数字,如果前面一个数字大于后面的数字,则这两个数字组成一个逆序对。给定一个数组,求出这个数组中的逆序对的总数。
  • 这个问题直接的做法是逐个统计,复杂度是O(n^2),但显然是很愚蠢的方法,这里可以利用归并排序的思想,在归并排序过程中统计逆序对的个数。
  • 实现思想: 
      归并排序是将数列a[l,r]分成两部分,a[l,mid]和a[mid+1,r]分别进行归并排序,然后再将这两半合并起来。在合并的过程中(设l<=i<=mid,mid+1<=j<=r),当a[i]<=a[j]时,并不产生逆序数;当a[i]>a[j]时,在前半部分中比a[i]大的数都比a[j]大,将a[j]放在a[i]前面的话,逆序数要加上mid+1-i。因此,可以在归并排序中的合并过程中计算逆序数。
  • C++实现:
#include <iostream>
using namespace std;
// 计算逆序数对的结果以long long返回
// 因为对于一个大小为n的数组, 其最大的逆序数对个数为 n*(n-1)/2, 非常容易产生整型溢出
// __merge函数求出在arr[l,mid]和arr[mid+1,r]有序的基础上, arr[l,r]的逆序数对个数
long long __merge(int arr[],int l,int mid,int r){
long long res = 0;// 初始化逆序数对个数 res = 0
int aux[r - l + 1];
for(int i = l;i <= r;i++)
aux[i - l] = arr[i];
int i = l;
int j = mid + 1;
for(int k = l;k <= r;k++){
if(i > mid){
arr[k] = aux[j - l];
j ++;
}
else if(j > r){
arr[k] = aux[i - l];
i ++;
}
else if(aux[i - l] < aux[j - l]){
arr[k] = aux[i - l];
i ++;
}
else{// 左半部分所指元素 > 右半部分所指元素
arr[k] = aux[j - l];
j ++;
res += (long long) (mid - i + 1);
// 此时, 因为右半部分所指的元素小
// 这个元素和左半部分的所有未处理的元素都构成了逆序数对
// 左半部分此时未处理的元素个数为 mid - j + 1
}
}
return res;
}
// 求arr[l,r]范围的逆序数对个数
long long __inversionCount(int arr[],int l,int r){
if(l >= r)
return 0;
int mid = l + (r - l) / 2;
long long res1 = __inversionCount(arr,l,mid);// 求出 arr[l,mid] 范围的逆序数
long long res2 = __inversionCount(arr,mid + 1,r);// 求出 arr[mid+1,r] 范围的逆序数
return res1 + res2 + __merge(arr,l,mid,r);
}
long long inversionCount(int arr[],int n){
return __inversionCount(arr,0,n - 1);
}
int main(){
int a[10] = {10,9,8,7,6,5,4,3,2,1};
int n = 10;
cout<< "逆序对数量为:" << inversionCount(a,n)<<endl;
}
  • Python实现:
 
def __merge(arr,l,mid,r):
res = 0
aux = []
for x in range(l,r + 1):
aux.append(arr[x])
i = l
j = mid + 1
for k in range(l,r + 1):
if i > mid:
arr[k] = aux[j - l]
j += 1
elif j > r:
arr[k] = aux[i - l]
i += 1
elif aux[i - l] < aux[j - l]:
arr[k] = aux[i - l]
i += 1
else:
arr[k] = aux[j - l]
j += 1
res += mid - i + 1
return res
def __inversionCount(arr,l,r):
if l >= r:
return 0
mid = l + (r - l) // 2
res1 = __inversionCount(arr,l,mid)
res2 = __inversionCount(arr,mid + 1,r)
return res1 + res2 + __merge(arr,l,mid,r)
def inversionCount(arr):
n = len(arr)
return __inversionCount(arr,0,n - 1)
arr = [10,9,8,7,6,5,4,3,2,1]
res = inversionCount(arr)
print("逆序对数量为:" + str(res))

 

3.取数组中第k大的元素

  • 题目很简单,给定一个数组,求出该数组中第k大的元素。最简单的做法是直接进行排序,算法复杂度是O(nlogn),但是这么做很明显比较低效率,因为只要求出第k大的元素,并不需要别的信息。
  • 另一种方法是用快速排序的思想。快速排序每次把一个元素交换到正确的位置,同时把左边的都放上小的,右边都放上大的。这个算法每一次选取一个中心点,排序之后,查看中心点的位置。如果它的位置大于K,就说明,要在前面一个子序列中找出第K大的元素。反之,如果小于K,就说明要在后面一个序列中找出第k大的元素。
  • 复杂度分析: 
      这种算法的复杂度分析稍微复杂。第一次交换,算法复杂度为O(n),接下来的过程和快速排序不同,快速排序是要继续处理两边的数据,再合并,合并操作的算法复杂度是O(1),于是总的算法复杂度是O(nlogn)(可以这么理解,每次交换用了n,一共logn次)。但是这里在确定中心点的相对位置(在K的左边或者右边)之后不用再对剩下的一半进行处理。也就是说第二次插入的算法复杂度不再是O(n)而是O(n/2),然后接下来的过程是1+1/2+1/4+........<2,换句话说就是一共是O(2n)的算法复杂度也就是O(n)的算法复杂度。 
      这个算法是一种很经典的算法。原因是因为它通过努力把算法复杂度在每次递归中下降一些,最终让整个算法的复杂度下降极多,算是一种十分聪明的做法。
  • C++实现:
#include <iostream>
#include <cstdlib>
#include <ctime>
using namespace std;
int __partition(int arr[],int l,int r){
swap(arr[l],arr[rand()%(r - l + 1) + l]);
int v = arr[l];
int j = l;
for(int i = l + 1;i <= r;i++){
if(arr[i] > v){
swap(arr[i],arr[j + 1]);
j ++;
}
}
swap(arr[l],arr[j]);
return j;
}
int __selection(int arr[],int l,int r,int k){
if(l == r)
return arr[l];
int p = __partition(arr,l,r);
if(p == k)
return arr[p];
else if(p > k)
return __selection(arr,l,p - 1,k);
else
return __selection(arr,p + 1,r,k);
}
int selection(int arr[],int n,int k){
srand(time(NULL));
return __selection(arr,0,n - 1,k - 1);//索引是从0开始的
}
int main(){
int arr[10] = {10,9,8,7,6,5,4,3,2,1};
int n = 10;
cout<<"数组中第3大的元素为:"<<selection(arr,n,3)<<endl;
}

 

  • Python实现:
import random
def __partition(arr,l,r):
k = random.randint(l,r)
arr[l],arr[k] = arr[k],arr[l]
v= arr[l]
j = l
for i in range(l + 1,r + 1):
if arr[i] < v:
arr[i],arr[j + 1] = arr[j + 1],arr[i]
j += 1
arr[l],arr[j] = arr[j],arr[l]
return j
def __selection(arr,l,r,k):
if l == r:
return arr[l]
p = __partition(arr,l,r)
if p == k:
return arr[p]
elif p > k:
return __selection(arr,l,p - 1,k)
else:
return __selection(arr,p + 1,r,k)
def selection(arr,k):
n = len(arr)
return __selection(arr,0,n - 1,k - 1)
arr = [10,9,8,7,6,5,4,3,2,1]
print("数组中第2小的元素为"+ str(selection(arr,2)))

推荐一个良心公众号【IT资源社】:

本公众号致力于免费分享全网最优秀的视频资源,学习资料,面试经验等,前端,PHP,JAVA,算法,Python,大数据等等,你想要的这都有

IT资源社-QQ交流群:625494093

也可添加微信拉你进微信群: super1319164238

微信搜索公众号:ITziyuanshe 或者扫描下方二维码直接关注,

 

 

编辑:顺马建文

发布:2019-04-19 00:00:00

当前文章:http://www.cnsdbtzg.com/6ofio/71707.html

到处求购蔷薇花?告诉你蔷薇花最大最集中的产区在哪里 哪里有大叶黄杨床苗销售基地? 高度20cm地柏苗多少钱一棵? 金边麦冬多少钱一棵? 公路绿化紫穗槐什么时间栽植? 哪里有卖玫瑰绿化工程苗? 多花紫藤品种有多少个? 11公分国槐价格多少钱一棵 340元上车价

17597 40967 39923 94751 84152 58783 64209 13561 67728 44439 52081 39255 66976 56938 28133 52722 95179 31177 72951 49516

我要说两句: (0人参与)

发布