请把纸条竖着放在桌⼦上,然后从纸条的下边向上⽅对折,压出折痕后再展 开。此时有1条折痕,突起的⽅向指向纸条的背⾯,这条折痕叫做“下”折痕 ;突起的⽅向指向纸条正⾯的折痕叫做“上”折痕。如果每次都从下边向上⽅ 对折,对折N次。请从上到下计算出所有折痕的⽅向。
给定折的次数n,请返回从上到下的折痕的数组,若为下折痕则对应元素为"down",若为上折痕则为"up".
1
返回:["down"]
请把纸条竖着放在桌⼦上,然后从纸条的下边向上⽅对折,压出折痕后再展 开。此时有1条折痕,突起的⽅向指向纸条的背⾯,这条折痕叫做“下”折痕 ;突起的⽅向指向纸条正⾯的折痕叫做“上”折痕。如果每次都从下边向上⽅ 对折,对折N次。请从上到下计算出所有折痕的⽅向。
给定折的次数n,请返回从上到下的折痕的数组,若为下折痕则对应元素为"down",若为上折痕则为"up".
1
返回:["down"]
python极其简单的解法,使用中序遍历。
class FoldPaper:
def foldPaper(self, n):
res = []
def midTraversal(n, postion):
if n == 0:
return
midTraversal(n - 1, "left")
if postion == "left":
res.append("down")
else:
res.append("up")
midTraversal(n - 1, "right")
midTraversal(n,"left")
return res
我们用一个假想的一维数组来模拟这个满二叉树,如果折叠N次,那么共有 2 N -1条折痕,也就是说,这棵想象中的满二叉树,有 2 N -1个结点。从1开始按层次遍历标号各结点。显然,除根结点外,偶数号结点均为左结点,奇数号结点均为右结点。也就是说,遇到偶数,就输出Down,遇到奇数,就输出Up.
用 迭代 来实现二叉树的中序遍历即可搞定。
classFoldPaper {public:vector<string> printFoldPaper(inti,intn,bool isDownOrUp){if(i>n)returndownOrUp;printFoldPaper(i+1,n,true);if(isDownOrUp)downOrUp.push_back("down");elsedownOrUp.push_back("up");printFoldPaper(i+1,n,false);returndownOrUp;}vector<string> foldPaper(intn) {// write code herereturnprintFoldPaper(1,n,true);}private:vector<string> downOrUp;};
Python简单解法:(非递归)(需要有可变数组实现)
折n次为n-1次的折痕结果中左右依次插入‘down’和‘up’
例如:
n=1:['down']
n=2:['down', 'down', 'up']
n=3:['down', 'down', 'up', 'down', 'down', 'up', 'up']
从前往后插缝隙就是先插‘down’,下一个插‘up’
我是从后往前插入缝隙就是先插‘up’,后插入‘down’
class FoldPaper:
def foldPaper(self, n):
result = ['down']
for i in range(n-1):
for j in range(len(result),-1,-1):
if j & 1:
result.insert(j,'up')
else:
result.insert(j,'down')
return result
public static String[] foldPaper(int n) {
int length = (1<<n) - 1 ;
int middle = length / 2;
String[] result = new String[length];
if(n == 1){
result[0] = "down";
return result;
}else{
result[0] = "down";
for(int i=1;i<=middle;i=i*2+1){
result[i] = "down";
for(int j=i-1;j>=0;j--){
int k = i-j;
if(result[j].equals("down")){
result[i+k] = "up";
}else{
result[i+k] = "down";
}
}
}
return result;
}
classFoldPaper {public:vector<string> printprocess(inti,intn,bool down){if(i>n)returnDownUpString;printprocess(i+1,n,true);if(down)DownUpString.push_back("down");elseDownUpString.push_back("up");printprocess(i+1,n,false);returnDownUpString;}vector<string> foldPaper(intn) {// write code herereturnprintprocess(1,n,true);}private:vector<string> DownUpString;};
import java.util.*;
public class FoldPaper {
public String[] foldPaper(int n) {
// write code here
List<String> list = new LinkedList<String>();
fold(n,list,"down");
String[] strs = new String[(int) (Math.pow(2,n)-1)];
return list.toArray(strs);
}
public static void fold(int n, List<String> list,String str){
if(n != 0){
fold(n-1,list,"down");
list.add(str);
fold(n-1,list,"up");
}
}
}
class FoldPaper:
def foldPaper(self, n):
return self.foldPapers(n,True)
def foldPapers(self,n,down):
if n==1:
return self.foldOnce(down)
return self.foldPapers(n-1,True) \
+ self.foldOnce(down) + self.foldPapers(n-1,False)
def foldOnce(self,down):
if down:
return ["down"]
else:
return ["up"]
给一个很长很窄的纸条,把纸条竖着放在桌子上,然后从纸条的下边向上方对折1次,压出折痕后展开,此时折痕是凹下去的,也就是突起的方向指向纸条的下方;
如果从纸条的下边向上方对折2次,压出折痕后展开,此时有三条折痕,从上到下依次是:下折痕、下折痕、上折痕;
如果纸条每次都从下边向上方对折,在对折n次之后展开。此时所有折痕突起的方向是什么样的呢?
请写一个函数,输入一个整数代表纸条的对折次数记为fTimes,从上到下依次打印所有折痕的突起方向。
例如:
fTimes = 1
打印:down
fTimes = 2
打印:down down up
提示:折痕其实是二叉树结构。该二叉树的特点是:根节点是下,每一个节点的左节点是下,右节点是上。该二叉树的中序遍历即为答案,但不需要构造一颗二叉树,用递归方法可打印出来。
classFoldPaper {public:vector<string> foldPaper(intn) {// write code herevector<string> v;pushs(v,n,"down");returnv;}voidpushs(vector<string> &v,intn,string s){if(n>0){pushs(v,n-1,"down");v.push_back(s);pushs(v,n-1,"up");}}};
n = 1, size = 1: "down",n = 2, size = 3: "down", "down", "up"n = 3, size = 7: "down", "down", "up", "down", "down", "up", "up"可以观察到每次迭代的时候,数组的新size是2*size+1. 前面的部分并没有改变,最中间的值永远是"down",后半部分直接把前面的值翻转一下就可以得到。class FoldPaper{public string[] foldPaper(intn){// write code hereint length = (2<< n-1) -1;string[] result = new string[length];int size =1;result[0] = "down";for(int i =2; i <= n; i++) {result[size] = "down";for(int j = size+1; j < 2* size +1; j++) {result[j] = result[2* size - j] =="down"?"up":"down";}size =2* size +1;}return result;}}
import java.util.*;
public class FoldPaper {
private ArrayList<String>res = new ArrayList<>();
public String[] foldPaper(int n) {
// write code here
printProcesses(1,n,true);
String []str= res.toArray(new String[]{});
return str;
}
public void printProcesses(int n, int N ,boolean down){
if (n>N){
return;
}
printProcesses(n+1,N,true);
res.add(down?"down":"up");
printProcesses(n+1,N,false);
}
/* public static void main(String[] args) {
String[]res = new FoldPaper().foldPaper(3);
for (String s:res){
System.out.println(s);
}
}*/
}
考察的是二叉树的中序遍历,可以试着折两下子,发现每一次折都会在最新的折痕上下位置出现两个新的折痕,一上一下,上为down,下为up。打印的时候,从上往下打印,类似于二叉树的中序遍历。
public String[] foldPaper(int n) {
// write code here
int length = 1;
for (int i = 0; i < n; i++) {
length = 2 * length;
}
length = length - 1;// 计算折痕数为2^n-1
String[] fold = new String[length]; if (n == 1) {
fold[0] = "down";// 只有一个折痕时
return fold;
} else if (n > 1) {
fold[0] = "down";
for (int j = 1; j <= (length / 2); j = (j * 2) + 1) {
fold[j] = "down";// 每次第(length+1)/2个折痕都为"down",并根据该折痕为中心点两侧相对
for (int k = j; k > 0; k--) {
if (fold[j - k].equals("down")) {
fold[j + k] = "up";
} else {
fold[j + k] = "down";
}
}
}
return fold;
} else {
return null;
}
}
递归中序遍历
import java.util.*;
public class FoldPaper {
public String[] foldPaper(int n) {
List<String> list = new LinkedList<String>();
listProcess(1,n,true,list);
int len = (2<< n-1) -1;
String[] strs = new String[len];
for(int i=0; i<len; i++){
strs[i] = list.get(i);
}
return strs;
}
public void listProcess(int i, int n, boolean isDown, List<String> list){
if(i>n){
return;
}
listProcess(i+1,n,true,list);
list.add(isDown?"down":"up");
listProcess(i+1,n,false,list);
}
}
我用的是二叉树的中序遍历做的,但是测试用例10通不过,郁闷
import java.util.*;
public class FoldPaper {
public String[] foldPaper(int n) {
// 初始 1 down
TreeNode root = createTree(n, 1);
StringBuilder sb = new StringBuilder();
printTree(root, sb);
return sb.toString().split(",");
}
/**
* 中序遍历构建二叉树
*
* @param k 折纸次数
* @param flag 1 凸 0 凹
* @return
*/
TreeNode createTree(int k, int flag) {
if (k <= 0) {
return null;
}
TreeNode left = createTree(k - 1, 1);
TreeNode node = new TreeNode(flag);
node.left = left;
TreeNode right = createTree(k - 1, 0);
node.right = right;
return node;
}
/**
* 中序遍历打印
*
* @param root
*/
void printTree(TreeNode node, StringBuilder sb) {
if (node == null) {
return;
}
printTree(node.left, sb);
sb.append(node.val == 1 ? "down" : "up").append(",");
printTree(node.right, sb);
}
static class TreeNode {
int val;
TreeNode left;
TreeNode right;
TreeNode() {
}
TreeNode(int val) {
this.val = val;
}
TreeNode(int val, TreeNode left, TreeNode right) {
this.val = val;
this.left = left;
this.right = right;
}
}
}