N诺刷题(基础算法)

目录

  • 玛雅人的秘密
  • 逆序对

玛雅人的秘密

玛雅人有一种密码,如果字符串中出现连续的2012四个数字就能解开密码。给一个长度为N的字符串,(2=

输入输出格式
输入描述:
输入包含多组测试数据,每组测试数据由两行组成。
第一行为一个整数N,代表字符串的长度(2<=N<=13)。
第二行为一个仅由0、1、2组成的,长度为N的字符串。
输出描述:
对于每组测试数据,若可以解出密码,输出最少的移位次数;否则输出-1。

参考https://www.jianshu.com/p/fa96e0c90e0e思路。
将原始字符串看作树的根节点,进行一次交换的字符串作为子节点,依次往下交换,然后使用广度优先搜索(BFS)遍历这棵树,也就是层序遍历每层的字符串对应一个 Map 值,含有2012的字符串在哪一层,就输出该层的 Map 值,如图 1 所示。保证树上的每个结点都不相同(map.find(key)查找是否有重复),直到穷尽。
N诺刷题(基础算法)_第1张图片

#include
using namespace std;
//const int maxn = 15; 
queue<string> Q;//用于BFS树
map<string,int> M;//用于存树的每层字符串对应的值,字符串的高度-1

string swap(string str,int i){//交换字符串第i和i+1 
	char temp;
	temp = str[i];
	str[i] = str[i+1];
	str[i+1] = temp;
	return str;
} 

int BFS(string str){
	string newStr;
	M.clear();//清空map
	while(!Q.empty()) Q.pop();//清空队列
	Q.push(str);
	M[str] = 0;
	while(!Q.empty()){
		str = Q.front();
		Q.pop();//取出队首
		for(int i =0;i<str.length()-1;i++){ //循环对每一位进行交换
			newStr = swap(str,i);//str交换i和i+1
			if(M.find(newStr)==M.end()){//这个字符串没出现过 
				M[newStr] = M[str]+1;//加入map
				if(newStr.find("2012")!=string::npos)//找到了2012 
					return M[newStr];
				else
					Q.push(newStr);//不符合要求,继续bfs 
			} 
		} 
	}
	return -1;// 遍历完,没有符合要求的字符串 
}

int main(){
	int n;
	string str;
	while(scanf("%d",&n) != EOF){
		cin >> str;
		if(n<4) cout<< -1<<endl;//肯定不符合要求
		else{
			if(str.find("2012") != string::npos)
				cout << 0;//初始字符串就有2012 
			else
				cout << BFS(str)<<endl;
		} 
	}
	return 0;
}

逆序对

猫猫 TOM 和小老鼠 JERRY 最近又较量上了,但是毕竟都是成年人,他们已经不喜欢再玩那种你追我赶的游戏,现在他们喜欢玩统计。
最近,TOM 老猫查阅到一个人类称之为“逆序对”的东西,这东西是这样定义的:对于给定的一段正整数序列,逆序对就是序列中 ai​>aj​ 且 i 输入:
第一行,一个数 n,表示序列中有 n个数(n < 10^5)。
第二行 n 个数,表示给定的序列。序列中每个数字不超过 10^9。

#include
using namespace std;
const int maxn = 500010;

int n;
int a[maxn],b[maxn];
long long ans = 0;
//归并排序
void merge(int L1,int R1,int L2,int R2){
	int i = L1,j = L2;
	int index = 0;//index为b数组的下标
	while(i<=R1 && j<=R2){
		if(a[i]<=a[j]){
			b[index++] = a[i++];
		}else{
			b[index++] = a[j++];
			ans += R1-i+1;//统计逆序对数 
		}
	} 
	while(i<=R1) b[index++] = a[i++];
	while(j<=R2) b[index++] = a[j++];
	for(int i =0;i<index;i++){
		a[L1+i] = b[i];//合并后的数组赋值回去 
	} 
}
void mergeSort(int l,int r){
	if(l == r) return;
	int mid = (l+r)/2;
	mergeSort(l,mid);
	mergeSort(mid+1,r);
	merge(l,mid,mid+1,r);
} 
int main(){
	scanf("%d",&n);
	for(int i =0;i<n;i++){
		scanf("%d",&a[i]);
	}
	mergeSort(0,n-1);
	printf("%lld\n",ans);
	return 0;
}

你可能感兴趣的:(刷题)