核心五部曲:
① 初始化元素数组[1,2,3,4],初始化方向数组[0,0,0,0] (0代表左移,1代表右移)
② 找到最大的可移动元素
可移动的两个条件:
1. 元素移动后不会越界([4,3,2,1],如果4方向为左,不能移动)
2. 即将交换的元素不能比本元素大([3,4,2,1],如果3的方向为右,不能移动)
③ 移动一次元素
④ 移动后,将元素列表中比移动元素大的所有元素的方向翻转(0-1,1-0)
⑤ 如果列表没有可以移动的元素,结束
#include<iostream>
#include<vector>
#include<algorithm>
using namespace std;
vector<int> nums; // 元素数组
vector<int> dir; // 方向数组,0代表左移,1代表右移
int n; // 元素数组大小
// 打印
void Print(){
for(int i = 0; i < n; i++) cout<<nums[i]<<" ";
cout<<endl;
}
// 调转当前移动元素更大的所有元素的方向
void changeDir(int num){
for(int i = 0; i < n; i++) {
if(num < nums[i]) {
if(dir[i] == 0) dir[i] = 1;
else dir[i] = 0;
}
}
}
// 交换位置
void SWAP(int id1, int id2) {
swap(nums[id1], nums[id2]);
swap(dir[id1], dir[id2]);
}
// 找到可以移动的最大元素
int canMove() {
int maxIndex = -1;
int maxNum = -1;
for(int i = 0; i < n; i++) {
if(dir[i] == 0 && i > 0 && nums[i] > nums[i - 1]) {
if(maxNum < nums[i]) {
maxIndex = i;
maxNum = nums[i];
}
}
else if(dir[i] == 1 && i < n - 1 && nums[i] > nums[i + 1]) {
if(maxNum < nums[i]) {
maxIndex = i;
maxNum = nums[i];
}
}
}
Print(); // 每一次交换都需要调用一次canMove函数,因此在此打印
return maxIndex;
}
// 移动
void move(int index) {
// 左移
if(dir[index] == 0 && index > 0 && nums[index] > nums[index - 1]) {
SWAP(index, index - 1);
}
// 右移
else if(dir[index] == 1 && index < n - 1 && nums[index] > nums[index + 1]){
SWAP(index, index + 1);
}
}
int main() {
cout << "Enter the size of number seq: ";
cin >> n;
// 初始化
for(int i = 0; i < n; i++) {
nums.push_back(i + 1);
dir.push_back(0); // 初始化元素都向左
}
while(true) {
// 1.找到可以移动的最大元素的索引
int moveIndex = canMove();
if(moveIndex != -1) {
int moveNumber = nums[moveIndex];
// 2.移动该元素
move(moveIndex);
// 3.移动完调转所有比它大的元素的方向
changeDir(moveNumber);
}
// 4.找不到可移动元素,结束循环
else break;
}
return 0;
}