请把纸条竖着放在桌⼦上,然后从纸条的下边向上⽅对折,压出折痕后再展 开。此时有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) { if (n == 0) return new String[0]; // write code here //就是个中序遍历 Queue<Node> queue = new LinkedList(); Node root = new Node("down"); queue.add(root); int height = 1; //这里是在用层序遍历建二叉树 while (true) { int num = queue.size(); while (num > 0) { Node cur = queue.poll(); cur.left = new Node("down"); queue.add(cur.left); cur.right = new Node("up"); queue.add(cur.right); num--; } //高度等于n说明建树完毕 if (++height == n) { break; } } //用逗号分隔得到数组 return inOrder(root).split(","); } static StringBuilder path = new StringBuilder(); 中序遍历拼接结果,用逗号做分割 public String inOrder(Node root) { if (root == null) return ""; inOrder(root.left); path.append(root.val+","); inOrder(root.right); return path.toString(); } } class Node { String val; Node right; Node left; public Node (String val) { this.val = val; } }