首页 > 其他分享 >冒泡排序最外层循环最少所需执行次数计算

冒泡排序最外层循环最少所需执行次数计算

时间:2024-08-02 18:49:56浏览次数:5  
标签:外层 01 return int 冒泡排序 flag 最少 ans sizeof

给定一个长为 \(n\) 的排列 \(a\),按下列代码执行排序,询问最终 \(ans\) 的值

inline int BF(){
	memcpy(b,a,sizeof(b));
	int ans=0;
	for(int i=1;i<n;++i){
		bool flag=1;
		for(int i=1;i<n;++i){
			if(b[i]>b[i+1]){
				flag=0;
				swap(b[i],b[i+1]);
			}
		}
		if(flag)return ans;
		++ans;
	}
	return ans;
}

解法

将原排列转化为 \(01\) 序列来做

从大到小枚举 \(k \in [1,n]\),新数组 \(b\) 中 \(b_i=(a_i\geq k)\)

找到最小的 \(l\),使得 \(\forall i\in [l,n]\),有 \(b_i=1\),定义 \(x=n-l+1\)(既这串靠右侧 \(1\) 的最长长度)

设 \(b\) 中 \(1\) 的个数为 \(s\)(容易发现 \(s=n-k+1\))

将这段 \(01\) 序列排序的最外层循环最少执行次数即为 \(s-x\),取所有 \(k\) 的最大值即可

用线段树维护 \(01\) 序列并求得最小的 \(l\),可以做到 \(O(n\log n)\) 的复杂度

还没写证明qwq,可能假了,不过简单对拍了一下没啥问题

丑陋的代码

#include <bits/stdc++.h>

using namespace std;

const int N=500005;
int n,a[N],b[N],loc[N];

int t[N<<2];
#define ls p<<1
#define rs p<<1|1
#define mid ((l+r)>>1)

inline void pushup(int p){t[p]=t[ls]+t[rs];}
void update(int p,int l,int r,int L){
	if(l==L&&r==L){
		++t[p];
		return;
	}
	if(L<=mid)update(ls,l,mid,L);
	else update(rs,mid+1,r,L);
	pushup(p);
}
inline int getans(int p,int l,int r){
	if(l==r){
		if(t[p])return l;
		return 0;
	}
	if(t[rs]==r-mid){
		int x=getans(ls,l,mid);
		if(x)return x;
		return mid+1;
	}
	return getans(rs,mid+1,r);
}

inline int BF(){
	memcpy(b,a,sizeof(b));
	int ans=0;
	for(int i=1;i<n;++i){
		bool flag=1;
		for(int i=1;i<n;++i){
			if(b[i]>b[i+1]){
				flag=0;
				swap(b[i],b[i+1]);
			}
		}
		if(flag)return ans;
		++ans;
	}
	return ans;
}

inline int solve01(){
	int ans=0;
	memset(b,0,sizeof(b));
	memset(t,0,sizeof(t));
	for(int i=1;i<=n;++i)loc[a[i]]=i;
	for(int i=n;i>=1;--i){
		update(1,1,n,loc[i]);
		//printf("update: %d\n",loc[i]);
		int x=getans(1,1,n);
		//printf("%d %d %d\n",i,t[1],x);
		if(x)ans=max(ans,t[1]-(n-x+1));
		else ans=max(ans,t[1]);
	}
	return ans;
}

int main(){
	scanf("%d",&n);
	for(int i=1;i<=n;++i)a[i]=i;
	/*for(int i=1;i<=n;++i)scanf("%d",&a[i]);
	printf("%d\n",BF());
	printf("%d\n",solve01());*/
	for(int T=1;T<=1000;++T){
		random_shuffle(a+1,a+1+n);
		/*for(int i=1;i<=n;++i)
			printf("%d ",a[i]);
		printf("\n");*/
		int x=BF(),y=solve01();
		if(x==y)printf("%d YES",T);
		else{
			puts("NO");
			for(int i=1;i<=n;++i)
				printf("%d ",a[i]);
			printf("%d %d\n",x,y);
			break;
		}
	}
	return 0;
}

最后

感谢 Winston12321_ 给我的启发,23级巨佬强得离谱

干打 markdown 没预览,可能写错了很多细节,不管了

标签:外层,01,return,int,冒泡排序,flag,最少,ans,sizeof
From: https://www.cnblogs.com/BigSmall-En/p/18339383

相关文章

  • 代码随想录算法训练营第二十六天|452. 用最少数量的箭引爆气球、435. 无重叠区间、763
    写代码的第二十六天继续贪心贪心!!!452.用最少数量的箭引爆气球思路最少的弓箭引爆气球,那么就是要看有没有重复覆盖的区域,如果有的话,那么一个弓箭就能引爆重复区域的气球,所以本题就是要看有多少气球是重复的,如果重复就用一根弓箭,如果不重复就加一。解决问题1:如何判断是否......
  • 冒泡排序
    冒泡排序(BubbleSort)冒泡排序是一种简单的交换排序算法。原理冒泡排序的每一趟都需要从第一位开始进行相邻的两个数的比较,将较大的数放在后面,比较完毕之后向后挪一位继续比较下面两个相邻的数的大小关系,重复此步骤,直到最后一个还没归位的数。示例:对数组[3,13,8,11,6,......
  • 冒泡排序
    特点:每一轮排序是将相邻的两个元素比较大小,最终是一个从小到大或者从大到小的有序序列。规律:1、轮次的规律:总共有n个元素,则需要比较n-1次2、每一轮的比较规律:每一轮的比较规律比上一轮-1次代码实现思想:至少需要两个变量参与编码,一个变量控制轮次,一个变量控制每一轮次中比较的次......
  • 冒泡排序的具体思想和算法实现以及改进
    冒泡排序——稳定算法从小到大排序:0~length-1对比a[0]和a[1],如果前一个大于后一个,交换位置。对比a[1]和a[2],如果前一个大于后一个,交换位置。对比a[2]和a[3],如果前一个大于后一个,交换位置。...对比a[length-2]和a[length-1],如果前一个大于后一个,交换位置。第一轮结果下......
  • 3111. 覆盖所有点的最少矩形数目
    给你一个二维整数数组 point ,其中 points[i]=[xi,yi] 表示二维平面内的一个点。同时给你一个整数 w 。你需要用矩形 覆盖所有 点。每个矩形的左下角在某个点 (x1,0) 处,且右上角在某个点 (x2,y2) 处,其中 x1<=x2 且 y2>=0 ,同时对于每个矩形都 必须 满足......
  • LeetCode 3111. 覆盖所有点的最少矩形数目(贪心、排序)
    题目:3111.覆盖所有点的最少矩形数目思路:只需关注横坐标,对横坐标进行升序排序,然后进行贪心,求得最少的矩阵数量classSolution{public:intminRectanglesToCoverPoints(vector<vector<int>>&points,intw){vector<int>v;for(inti=0;i<poi......
  • Leetcode每日一题 20240731 3111.覆盖所有点的最少矩阵数目
    题目描述给你一个二维整数数组point,其中points[i]=[xi,yi]表示二维平面内的一个点。同时给你一个整数w。你需要用矩形覆盖所有点。每个矩形的左下角在某个点(x1,0)处,且右上角在某个点(x2,y2)处,其中x1<=x2且y2>=0,同时对于每个矩形都必须满足x2......
  • 【排序算法(二)】——冒泡排序、快速排序和归并排序—>深层解析
    前言:    接上篇,排序算法除了选择排序(希尔排序)和插入排序(堆排序)之外,还用交换排序(冒泡排序、快速排序)和归并排序已经非比较排序,本篇来深层解析这些排序算法一、交换排序    1.1、冒泡排序    冒泡排序,这个再熟悉不过了,学校中老师讲的第一个排序就......
  • 两种常见排序(冒泡排序和选择排序)详解
    一、冒泡排序1.1、冒泡排序的原理讲解。例如有以下7个数的无序数列储存在数组arr[7]中,现在需要用冒泡排序法来对以下序列进行排序冒泡排序是比较相邻的两个数,如果第一个数比第二个数大,这两个数就要交换两个数的位置,如果第一个数小于第二个数则不用变换位置,例如第一个数3比......
  • numpy 中用最少内存对上三角元素求和的最快方法
    我需要对对称矩阵进行类型求和i<j这相当于对矩阵的上三角元素求和,不包括对角线。给定A对称NxN数组,最简单的解决方案是np.triu(A,1).sum()但是我想知道是否存在需要更少内存的更快方法。看起来(A.sum()-np.diag(A).sum())/2......