今天遇到几个比较好玩的题目~~
题目一
折纸问题
【题目】请把一段纸条竖着放在桌子上,然后从纸条的下边向上方对折1次,压出折痕后展开。此时折痕是凹下去的,即折痕突起的方向指向纸条的背面。如果从纸条的下边向上方连续对折2次,压出折痕后展开,此时有三条折痕,从上到下依次是下折痕、下折痕和上折痕。给定一个输入参数N,代表纸条没次都从下边向上方连续对折N次,请从上到下打印所有折痕的方向。
例如:N=1时,打印:
down
N=2时,打印:
down
down
up
通过折纸发现,第k次产生的折痕,在第k+1次会产生一个down跟一个up。
实际上就是 二叉树中序遍历。
#include <iostream>
#include <algorithm>
#include <cstdio>
#include <cstring>
#include <string>
using namespace std;
const int N=1e3+10;
void dfs(int id, int n, bool flag){
if(id>n) return;
dfs(id+1, n, true);
if(flag) printf("down\n");
else printf("up\n");
dfs(id+1, n, false);
}
int main(){
int n;
while(~scanf("%d", &n)){
dfs(1, n, true);
}
return 0;
}
题目二
旋转字符串
【题目】
给定一个字符类型的数组chas和一个整数size,请把大小为size的左半区整体移到右半区,右半区整体移到左边。
【举例】
如果把chas看作字符串为"ABCDE",size=3,调整成"DEABC"。
【要求】
如果chas长度为N,两道题都要求时间复杂度为O(N),额外空间复杂度为O(1)。
前半段逆序,后半段逆序,然后总体逆序。
#include <iostream>
#include <algorithm>
#include <cstdio>
#include <cstring>
#include <string>
using namespace std;
const int N=1e3+10;
int a[N];
int main(){
int n;
while(~scanf("%d", &n)){
for(int i=1; i<=n; i++) scanf("%d", &a[i]);
int ida=1, idb=n/2;
while(ida<idb) swap(a[ida], a[idb]), ida++, idb--;
ida=(n+1)/2, idb=n;
while(ida<idb) swap(a[ida], a[idb]), ida++, idb--;
ida=1, idb=n;
while(ida<idb) swap(a[ida], a[idb]), ida++, idb--;
for(int i=1; i<=n; i++) {
if(i==n) printf("%d\n", a[i]);
else printf("%d ", a[i]);
}
}
return 0;
}
扩展:
将前a个跟后b个交换
小块换过来的部分定住不动,产生的两个新快继续换
直到两个产生的新块大小相等,交换之后就结束
以下是将12 跟34567交换的过程,绿色表示交换之后固定不动,蓝色表示产生的两个新块
题目三
数组先小于等于再大于等于的调整
【题目】
给定数组arr,请将数组调整成a <= b >= c <= d >= e <= f...的样子
【举例】
arr = {3,1,2}
调整之后,arr可以是{1,3,2}. 1 <= 3 >=2
调整之后,arr也可以是{2,3,1}. 2 <= 3 >=1
arr = {3,1,2,6}
调整之后,arr可以是{1,6,2,3}. 1 <= 6 >= 2 <= 3
调整之后,arr也可以是{3,6,1,2}. 3 <= 6 >= 1 <= 2
【要求】
1,如果arr长度为N,要求时间复杂度为O(N),额外空间复杂度为O(1)。
2,arr可能会不止一种调整方案,但只要满足要求即可。
原题:完美洗牌问题
完美洗牌问题驱动点不止一个
结论:
如果数组的长度是(3^k-1),它的驱动点是1、3、9…… 3^(k-1),数组的初始位置是1
数组长度不是(3^k-1),那就采用分块思想,将长度拆成(3^k-1)
循环小数化分数
1,纯循环小数:小数点后有几位数,分母就有几个9,分子为一个循环节.如:0.345(345循环)=345/999 该化简就化简即可.
2,混循环小数:小数点后到第一个循环减去非循环小数部分作为分子,循环节内有几位数,分母就有几个9,然后接着写几个0,0的个数为第一个循环节前面非循环小数的位数.如:0.0231(31循环)=(0231-02)/9900 需要化简再化简.
题目四
在数组中找到第k小的数
【要求】
如果arr长度为N,要求时间复杂度为O(N),额外空间复杂度为O(1)。
quick select:随机选一个数x,将小于等于x的放他左边,否则放右半段,看k在左半端还是在右半段,继续上述过程
荷兰国旗问题:quick select优化 分三段,小于放左边,等于x放中间,大于x放右边
BFPRT算法