2016.10.12算法精讲第十一章

今天遇到几个比较好玩的题目~~


题目一

折纸问题

【题目】
请把一段纸条竖着放在桌子上,然后从纸条的下边向上方对折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算法


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值