【笔试练习题】双端放石子排序

2017百度春招笔试题里面有一题是这样的:

度度熊有一个N个数的数组,他想将数组从小到大 排好序,但是萌萌的度度熊只会下面这个操作:
任取数组中的一个数然后将它放置在数组的最后一个位置。
问最少操作多少次可以使得数组从小到大有序?

这篇博客里面提供了解法:https://blog.csdn.net/weixin_39530880/article/details/82315709

2019年的2020浪潮秋招有一道笔试题是也差不多,不过要求可以拿出的数字放在最前面或者最后面。而且保证数组中没有重复数字。

我的解法如下(但是找不到哪里可以跑case,因此并没有试验过)。

#include 
using namespace std;

bool is_ordered(const list &v) {
	auto it1 = v.begin();
	auto it2 = v.begin();
	it2++;
	while (it2 != v.end()) {
		if (*it2 < *it1) {
			return false;
		}
		it1++;
		it2++;
	}
	return true;
}

int get_ans(list &v) {
	if (is_ordered(v)) {// 如果是有序的,就直接返回, 需要调整0次
		return 0;
	}
	// 如果不是有序的
	// 1. 找到最大值和最小值
	auto it_max = v.begin();
	auto it_min = v.begin();
	for (auto it = v.begin(); it != v.end(); ++it) {
		if (*it > *it_max) {
			it_max = it;
		}
		if (*it < *it_min) {
			it_min = it;
		}
	}
	// 2. 判断只调整最小值之后是不是有序的
	int num_min = *it_min; // 保存最小值
	it_min = v.erase(it_min); // 删除最小值
	if (is_ordered(v)) {
		v.push_front(num_min);
		return 1; // 返回: 需要进行1次调整
	}
	else {
		it_min = v.insert(it_min, num_min); // 否则撤销删除最小值的操作
	}
	// 2. 判断只调整最大值之后是不是有序的
	int num_max = *it_max; // 保存最大值
	it_max = v.erase(it_max); // 删除最大值
	if (is_ordered(v)) {
		v.push_back(num_max);
		return 1; // 返回: 需要进行1次调整
	}
	
	// 3. 如果都不是,那就还要继续递归
	v.erase(it_min); // 把最大值和最小值都删除
	int cnt = get_ans(v); // 此时返回的时候剩余list里面的n - 2个节点已经排序了
	v.push_back(num_max);
	v.push_front(num_min);
	return cnt + 2;
}

int main() {
	int n = 0;
	while (cin >> n) {
		list v;
		for (int i = 0; i < n; ++i) {
			int x;
			cin >> x;
			v.push_back(x);
		}
		int deep = get_ans(v);
		cout << deep << endl;
	}
	return 0;
}

 

你可能感兴趣的:(笔试题)