**
1.输入n个数,奇数在前,偶数在后,分别由小到大排序。
**
例如输入:[8,4,2,1],输出[1,2,4,8]。
输入:[1,2,3,4,5,6,7,8],输出[1,3,5,7,2,4,6,8]
思路:
1.先把奇数放到头部,偶数沉到尾部。
2.分别对奇序列和偶序列进行快排。
相关知识点:快排,双指针
快排是对冒泡排序的一种改进。每次快速排序选中一个privot基准数,将比privot小的数放到privot左边,大的放到右边。对一个数组进行快速排序,一共要进行logn次这样的操作。时间复杂度为O(nlogn)。
手写快排:
void quickSort(int left,int right,int* (&array)){
int recordLeft = left; //保存初始left指针
int recordRight = right; //保存初始right指针
bool isLeftPoint = false; //初始指针从右开始
if(left<right){
int privot = array[left]; //每次选取的基准数
while(true){
if(left == right){
array[left] = privot; //left=right,一次快排结束。
break;
}else{
if(!isLeftPoint){ //指针在右面
if(array[right]<privot){
array[left] = array[right];
left += 1;
isLeftPoint = true;
}else{
right -= 1;
}
}else{
if(array[left]>privot){
array[right] = array[left];
right -= 1;
isLeftPoint = false;
}else{
left += 1;
}
}
}
}
quickSort(recordLeft,left-1,array); //递归对privot左进行快排
quickSort(left+1,recordRight,array);//递归对privot右进行快排
}
}
区分奇偶的操作我们也可以借鉴这个双指针的思想。左指针指向首元素,右指针指向尾元素,最后返回最后一个奇数的下标。
具体来说,分四种情况。
1.如果左指针指向的数是奇数,右指针指向的数是偶数,左指针后移,右指针前移。
2.如果左指针指向的数是偶数,右指针指向的数是奇数,交换左右指针的数,左指针后移,右指针前移。
3.如果左右指针指向的数都是奇数,左指针后移。
4.如果左右指针指向的数均是偶数,右指针前移。
如果左指针大于右指针,break。
int jiOu(int left,int right,int* (&array)){
int tmp;
while(true){
if(left>right){
break;
}else{
if((array[left]%2 == 1)&&(array[right]%2 ==0)){
left += 1;
right -= 1;
}else if((array[left]%2 == 0)&&(array[right]%2 ==1)){
tmp = array[left];
array[left] = array[right];
array[right] = tmp;
left += 1;
right -= 1;
}else if((array[left]%2 == 1)&&(array[right]%2 ==1)){
left += 1;
}else{
right -= 1;
}
}
}
return right;
}
主函数
int main(){
int num;
cin>>num; //输入几个数
int array[num];
int input;
for(int i=0;i<num;i++){
cin>>input;
array[i] = input;
}
int* arrayPoint = array;
int jiBoard = jiOu(0,num-1,arrayPoint); //划分奇偶序列
quickSort(0,jiBoard,arrayPoint);//奇数快排
quickSort(jiBoard+1,num-1,arrayPoint);//偶数快排
for(int i=0;i<num;i++){ //打印结果。
cout<<array[i]<<" ";
}
return 0;
}
**
2.最大连续子序列
**
输入一个数组array,输出其最大连续子序列的和。
如array = [-2 11 -4 13 -5 -2]输出20。11 -4 13为最大子序列。
思路:
定义sum(i,j)表示从i到j的子序列的和。
定义一个长度为n的一维数组record,其中第k个元素记录max{sum(1,k),sum(2,k)…sum(k,k)}。
则有:
record[n] = array[0] (n = 0)
record[n] = max{record[n-1]+array[n],array[n]}
则最长子序列的和就是:
max{record[1],record[2],…record[n]}
#include <iostream>
using namespace std;
int maxNum(int num1,int num2);
int main(){
int arrayNum; //输入要输入数的个数
cin>>arrayNum;
int* array = (int *) malloc(sizeof(int) * arrayNum);
for(int i=0;i<arrayNum;i++){
int num;
cin>>num;
array[i] = num; //输入要求解的数组array
}
int sum = 0;
int* record = (int*) malloc(sizeof(int)*arrayNum);
record[0] = array[0];
int result = record[0]; //最大连续子序列结果
for(int i=1;i<=arrayNum-1;i++){
record[i] = maxNum(record[i-1]+array[i],array[i]); //计算record
if(result<record[i]){
result = record[i]; //找到更大得最长子序列,更新结果。
}
}
cout<<result;
return 0;
}
int maxNum(int num1,int num2){
/*
返回num1和num2中的最大值
*/
return (num1>=num2)?num1:num2;
}
3.汉诺塔
A柱上有n个盘,怎么原封不动移到C柱上,大盘不能压小盘。5个一行,打印移动序列。
例如输入2:就打印:
A–>B A–>C B–>C
输入1:就打印:
A–>C
输入0退出。
思路:考虑子问题。
n = 1
A–>C
n = 2
A–>B 将2-1(n-1)个盘从A–>B
A–>C
B–>C 将2-1(n-1)个盘从B–>C
n = 3
A–>C 将3-1(n-1)个盘从A–>B
A–>B
C–>B
A–>C
B–>A 将3-1(n-1)个盘从B–>C
B–>C
A–>C
通过观察我们发现,将n个盘从A–>C由三部分组成:
1.将n-1个盘从A–>B(中转柱)
2.将1个盘(A最底下那个盘)从A–>C
3.将n-1个盘从B(中转柱)–>C
这里的B是一个中转柱。比如某任务要求把k个盘从柱A运到柱C,B就是中转柱。
写一个求中转柱的函数。
char getFree(int a,int b){
if(a=='A'){
if(b == 'B'){
return 'C';
}else if(b == 'C') {
return 'B';
}
}else if(a =='B'){
if(b =='A'){
return 'C';
}else if(b == 'C'){
return 'A';
}
}else{
if(b =='A'){
return 'B';
}else if(b == 'B'){
return 'A';
}
}
}
有了以上的递归思想,就可以编写出把num个盘从start柱移动到end柱的函数。
void sOutStep(char start,char end,int num){
/*
count用于计数,5个一换行
*/
if(num == 1){
if((count%5==0)&&(count!=0)){
cout<<endl;
}
cout<<start<<"-->"<<end<<" ";
count++;
}else{
char free = getFree(start,end); //中转柱
//第一步:递归
sOutStep(start,free,num-1);
//第二部:A-->C
if((count%5==0)&&(count!=0)){
cout<<endl;
}
cout<<start<<"-->"<<end<<" ";
count++;
//第三步:递归
sOutStep(free,end,num-1);
}
}
最后主函数如下:
int count = 0; //用于换行计数,全局变量。
int main(){
bool loop = true;
int num;
while(loop){
cin>>num;
switch(num){
case 0: //输入0,退出程序。
loop = false;
break;
default: //否则,打印把n个盘从'A'移动到'C'的序列。
count = 0;
sOutStep('A','C',num);
cout<<endl;
break;
}
}
return 0;
}
**
4.输出菱形
**
输入一个整数n,控制台输出对应的菱形,例如:
n = 1;
输出:
n = 3;
输出
思路:找规律,每一行先输出若干空格,再输入若干个*。
#include<iostream>
using namespace std;
void printlonzenge(int num);
int main(){
int num;
cin>>num;
printlonzenge(num);
return 0;
}
void printlonzenge(int num){
for(int i = 1;i<2*num;i++){
for(int j = 0;j<((num-i>0)?(num-i):(-num+i));j++){
cout<<' ';
} //输出若干个空格
for(int k = 0;k<((i<=num)?2*i-1:4*num-2*i-1);k++){
cout<<'*';
} //输出若干个*
cout<<endl;
}
}