其他一些小技巧和算法

1. 打表

    1,在程序中一次性计算出所有需要用到的结果,之后的查询直接取这些结果

    2,在程序B中分一次或多次计算出所有需要用到的结果,手工把结果写在程序A的数组中,然后再程序A中直接使用这些结果

    3,对一些感觉不会做的题目,先用暴力程序计算小范围数据的结果,然后找规律

2. 随机选择算法

    从一个无序的数组中求出第K大的数

    题目:给定一个由整数组成的集合,集合中的整数各不相同,现在要将它分为两个子集合,使得这两个子集合的并为原集合、交为空集,同时在两个子集合的元素个数n1与n2之差的绝对值|n1-n2|尽可能小的前提下,要求它们各自的元素之和S1与S2之差的绝对值|S1-S2|尽可能大。求|S1-S2|

#include <cstdio>
#include <ctime>
#include <cstdlib>
#include <algorithm>
#include <cmath>

using namespace std;
const int maxn = 100010;
int A[maxn],n;

//选取随机主元,对区间[left,right]进行划分
int randPartition(int A[],int left,int right){
	//生成[left,right]内的随机数p
	int p = (round(1.0*rand()/RAND_MAX*(right-left)+left));
	swap(A[p],A[left]); // 交换A[p]和A[left]
	//以下为原先Partition函数划分的过程,不需要改变任何东西
	int temp = A[left];
	while(left<right){
		while(left<right && A[right]<temp) right--;
		A[left]=A[right];
		while(left<right && A[left]<=temp) left++;
		A[left]=A[right];
	}
	A[left] = temp;
	return left;
}


//随机选择算法,在[left,right]中返回第K大的数
int randSelect(int A[],int left,int right,int K){
	if(left==right) return A[left];  //边界
	int p = randPartition(A,left,right); //划分后主元的位置为p
	int M = p-left+1; //A[p]是A[left,right]中的第M大
	if(K == M) return A[p];  //找到第K大的数
	if(K < M)  return randSelect(A,left,p-1,K);    //往主元左侧找第K大
	else       return randSelect(A,p+1,right,K-M); //往主元右侧找第K-M大
}

int main() {
	srand((unsigned)time(NULL));    //初始化随机数种子
	//sum 和 sum1记录所有整数之和和与切分后前n/2个元素之和
	int sum=0,sum1=0;
	scanf("%d",&n); //整数个数
	for(int i=0;i<n;i++){
		scanf("%d",&A[i]);
		sum+=A[i];  //累计所有整数之和
	}
	randSelect(A,0,n-1,n/2);   //寻找第n/2大的数,并进行切分
	for(int i=0;i<n/2;i++){
		sum1+=A[i]; //累计较小的子集合中元素之和
	}
	printf("%d\n",(sum-sum1)-sum1); //求两个子集合的元素和之差
	return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

猪突猛进!

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值