找工作--笔试面试--准备4

1、Distinct Subsequences

Given a string S and a string T, count the number of distinct subsequences of T in S.

A subsequence of a string is a new string which is formed from the original string by deleting some (can be none) of the characters without disturbing the relative positions of the remaining characters. (ie, "ACE" is a subsequence of "ABCDE" while "AEC" is not).

Here is an example:
S = "rabbbit"T = "rabbit"

Return 3.

题意很好理解了,自序列定义为,顺序不变,中可以插入字符的一个序列。通过删除一些字符,就可以得到目标字符串,但是不能改变所有字符串的顺序。然后返回所以字符串的数量。

还是有些忘掉了,看了下原理才知道,知道这个是用动态规划,不过还是没想起来怎么个动态规划法。
动态规划:用一维数组记录S的字符串某个位置之前m个字符串,含有多少个T的前n个字符串。A[m][n] = A[m-1][n]+A[m-1][n-1](if S[m] == T[n]);
int numDistinct(string S, string T) {
		int lens = S.size();
		int lent = T.size();
		if(lent>lens||lens == 0||lent == 0){
			return 0;
		}
		vector<vector<int> > vec;
		for(int i = 0;i<lens;i++){
			vector<int> tmp(lent);
			vec.push_back(tmp);
			if(S[i] == T[0]){
				vec[i][0] = 1;//--------------1
			}
			for(int j = i+1;j<lent;j++){
				vec[i][j] = 0;
			}
		}//初始化动态规划数组
		for(int i = 1;i<lens;i++){
			if(S[i]==T[0]){
				vec[i][0] = vec[i-1][0]+1;
			}
			else{
				vec[i][0] = vec[i-1][0];
			}//这里和1处其实可以合并
			for(int j = 1;j<=i&&j<lent;j++){
				if(S[i]==T[j]){
					vec[i][j] = vec[i-1][j]+vec[i-1][j-1];
				}
				else{
					vec[i][j] = vec[i-1][j];
				}
			}
		}
		return vec[lens-1][lent-1];
    }

2、Flatten Binary Tree to Linked List

 

Given a binary tree, flatten it to a linked list in-place.

For example,
Given

         1
        / \
       2   5
      / \   \
     3   4   6

The flattened tree should look like:
   1
    \
     2
      \
       3
        \
         4
          \
           5
            \
             6

这个是先序遍历。主要的突破点是将右子树嫁接到左子树的最右子树的右子树上,这样可以一次遍历。访问3将4嫁接到3右孩子上,然后将3移植到2的右孩子上,递归遍历。因为最终要的是将树改造为一个先序遍历的以右孩子为主线的链表。

void flatten(TreeNode *root) {
		preorder(root);
    }
	void preorder(TreeNode *root){
		 if(root == NULL){
			return;
		 }
		 if(root->left!=NULL){
			 preorder(root->left);
			 TreeNode *cur = root->left;
			 while(cur->right!=NULL){
				 cur = cur->right;
			 }
			 cur->right = root->right;
			 root->right = root->left;
			 root->left = NULL;
		 }
		 if(root->right!=NULL){
			 preorder(root->right);
		 
		 }
	 }

3、Path Sum

 I II

Given a binary tree and a sum, determine if the tree has a root-to-leaf path such that adding up all the values along the path equals the given sum.

For example:
Given the below binary tree and  sum = 22 ,
              5
             / \
            4   8
           /   / \
          11  13  4
         /  \      \
        7    2      1

return true, as there exist a root-to-leaf path 5->4->11->2 which sum is 22.

深度遍历好了

bool dfs(TreeNode *node, int sum, int curSum)
     {
         if (node == NULL)
            return false;
         
         if (node->left == NULL && node->right == NULL)
             return curSum + node->val == sum;
                
         return dfs(node->left, sum, curSum + node->val) || dfs(node->right, sum, curSum + node->val);
     }
     
     bool hasPathSum(TreeNode *root, int sum) {
         return dfs(root, sum, 0);
     }

Given a binary tree and a sum, find all root-to-leaf paths where each path's sum equals the given sum.

For example:
Given the below binary tree and  sum = 22 ,
              5
             / \
            4   8
           /   / \
          11  13  4
         /  \    / \
        7    2  5   1

return

[
   [5,4,11,2],
   [5,8,4,5]
]
深度遍历,中间添加vector 中间变量。这个题目其实,我有点想错了的地方是,题目要求是root到leaf,我理解成了root到中间一个随便一个结点都可以的。

class Solution {
private:
	vector<vector<int> > path;
public:
	vector<vector<int> > pathSum(TreeNode *root, int sum) {
		vector<int> temppath;
		path.clear();
		PathTree(root,0,sum,temppath);
		return path;
    }
	void PathTree(TreeNode * root,int num,int sum,vector<int> temppath){
		if(root == NULL){
			return ;
		}
		if(root->left==NULL&&root->right==NULL){
			if(root->val+num == sum){
				temppath.push_back(root->val);
				path.push_back(temppath);
				return ;
			}
			else
				return ;
		}
		temppath.push_back(root->val);
		if(root->left == NULL){
			PathTree(root->right,num+root->val,sum,temppath);
		}
		else if(root->right == NULL){
			
			PathTree(root->left,num+root->val,sum,temppath);
		}
		else{
		PathTree(root->right,num+root->val,sum,temppath);
		PathTree(root->left,num+root->val,sum,temppath);
		    
		}
	}
};
4、

Minimum Depth of Binary Tree && 

Maximum Depth of Binary Tree

 

Given a binary tree, find its minimum depth.

The minimum depth is the number of nodes along the shortest path from the root node down to the nearest leaf node.

深度遍历,计算层数,注意,叶子的定义,左右孩子为空。

int minDepth(TreeNode *root) {
		if(root == NULL){
			return 0;
		}
		if(root->left == NULL&&root->right == NULL){
			return 1;
		}
		int leftdepth = minDepth(root->left);
		int rightdepth = minDepth(root->right);
		if(leftdepth == 0){
			return rightdepth+1;
		}
		else if(rightdepth == 0){
			return leftdepth+1;
		}
		return min(leftdepth,rightdepth)+1;//------------------------------1
    }

Given a binary tree, find its maximum depth.

The maximum depth is the number of nodes along the longest path from the root node down to the farthest leaf node.

按minimum的想法,只需要将1处的代码修改为max函数即可,下面这个是另一种实现方式,不过大同小异。

int maxDepth(TreeNode *root) {
		if(root == NULL){
		 return 0;
		}
        int depth = 0,maxdepth = 0;
		treverse(root,depth,maxdepth);
		return maxdepth;
    }
	void treverse(TreeNode *root,int depth,int & maxdepth){
		if(root == NULL){
			return;
		}
		depth ++;
		if(depth>maxdepth){
			maxdepth = depth;
		}
		treverse(root->left,depth,maxdepth);
		treverse(root->right,depth,maxdepth);
	}


5、Balanced Binary Tree  

Given a binary tree, determine if it is height-balanced.

For this problem, a height-balanced binary tree is defined as a binary tree in which the depth of the two subtrees of every node never differ by more than 1.

还是递归dfs,深度优先。。。我这里的方法是函数返回值为int,但是中间传参数是引用,bool。做到这里,做了这么多的dfs树类的,越做越顺手。

bool isBalanced(TreeNode *root) {
		if(root == NULL){
			return true;
		}
        bool result = true;
		Dlength(root,result);
		return result;
    }
	int Dlength(TreeNode * root,bool &result){
	    if(result == false){
			return 0;
		}
		if(root == NULL){
			return 0;
		}
		if(abs(Dlength(root->left,result)-Dlength(root->right,result))>1){
			result = false;
		}
		return max(Dlength(root->left,result)+1,Dlength(root->right,result)+1);
	}
6、Convert Sorted List to Binary Search Tree

Given a singly linked list where elements are sorted in ascending order, convert it to a height balanced BST.
链表是升序排列的,首先想到的是如何构造一个二叉树。一开始想到的就是将链表中间进行折半,然后两边继续折半。折半的中间元素作为root,这样保证生成的二叉树,两个子树的深度相差最大为1,都是从中间进行折半的。如果说理论,目前不清楚。

给出的代码是转换为下面array的方案,还有一种就是根据链表,快慢指针进行扫到中间的结点,然后进行处理。

Convert Sorted Array to Binary Search Tree

Given an array where elements are sorted in ascending order, convert it to a height balanced BST.

这两个题目的原理是一样,前面是将链表转换为vector的array就和后面的题目一样了。

array

TreeNode *sortedArrayToBST(vector<int> &num) {
		if(num.size() == 0){
			return NULL;
		}
		return built(num,0,num.size()-1);
    }
	TreeNode * built(vector<int> &num,int start,int end){
		if(start>end){
			return NULL;
		}
		TreeNode * p = NULL;
		if(start == end){
			p = new TreeNode(num[start]);
			return p;
		}
		int mid = (start+end)/2;
		p = new TreeNode(num[mid]);
		p->left = built(num,start,mid-1);
		p->right = built(num,mid+1,end);
		return p;
	}
list

TreeNode *sortedListToBST(ListNode *head) {
        vector<int> vec;
		vec.clear();
		ListNode *p = head;
		while(p!=NULL){
			vec.push_back(p->val);
			p = p->next;
		}
		return GetTree(vec,0,vec.size()-1);
    }
	TreeNode * GetTree(vector<int>&vec,int start,int end){
		if(start>end){
			return NULL;
		}
		int mid = (start+end)/2;
		TreeNode * p = new TreeNode(vec[mid]);
		p->left = GetTree(vec,start,mid-1);
		p->right = GetTree(vec,mid+1,end);
		return p;
	}

7、Binary Tree Level Order Traversal

 I II

Given a binary tree, return the level order traversal of its nodes' values. (ie, from left to right, level by level).

For example:
Given binary tree {3,9,20,#,#,15,7},

    3
   / \
  9  20
    /  \
   15   7

return its level order traversal as:

[
  [3],
  [9,20],
  [15,7]
]

confused what "{1,#,2,3}" means? > read more on how binary tree is serialized on OJ.


OJ's Binary Tree Serialization:

The serialization of a binary tree follows a level order traversal, where '#' signifies a path terminator where no node exists below.

Here's an example:

   1
  / \
 2   3
    /
   4
    \
     5
The above binary tree is serialized as  "{1,2,3,#,#,4,#,#,5}".
队列保存中间结点,输出上一层的数据的时候将下一层的孩子加入队列。
vector<vector<int> > levelOrder(TreeNode *root) {
		vector<vector<int> > ret;
		ret.clear();
		if(root == NULL){
			return ret;
		}
        queue<TreeNode*> q;
        q.push(root);
		while(!q.empty()){
			int len = q.size();
			vector<int> que;
			while(len>0){
				TreeNode * cur = q.front();
				que.push_back(cur->val);
				if(cur->left!=NULL){
					q.push(cur->left);
					
				}
				if(cur->right!=NULL){
					q.push(cur->right);
				}
				q.pop();
				len -- ;
			}
			ret.push_back(que);
		}
		return ret;
    }

Given a binary tree, return the bottom-up level order traversal of its nodes' values. (ie, from left to right, level by level from leaf to root).

For example:
Given binary tree {3,9,20,#,#,15,7},

    3
   / \
  9  20
    /  \
   15   7

return its bottom-up level order traversal as:

[
  [15,7],
  [9,20],
  [3]
]
这个题目是将输出的序列反过来,先输出最后一层,然后上一层。如果按第一题的想法,这个也是可以做的,无非就是将上面的输出结果reverse一下就可以了。

这个题目是定义了两个数据结构,一个是vector<queue<>>保存的是每一层遍历的结点,然后将结点的queue加入vector vector

vector<vector<int> > levelOrderBottom(TreeNode *root) {
        vector<vector<int> > ret;
		ret.clear();
		if(root == NULL){
			return ret;
		}
		vector<queue<int>> vec;
        queue<TreeNode*> q;
		q.push(root);
		while(!q.empty()){
			int len = q.size();
			queue<int> que;
			while(len>0){
				TreeNode * cur = q.front();
				que.push(cur->val);
				if(cur->left!=NULL){
					q.push(cur->left);
					
				}
				if(cur->right!=NULL){
					q.push(cur->right);
				}
				q.pop();
				len -- ;
			}
			vec.push_back(que);
		}
		for(int i=vec.size()-1;i>=0;i--){
			vector<int> tmp;
			while(!vec[i].empty()){
				tmp.push_back(vec[i].front());
				vec[i].pop();
			}
			ret.push_back(tmp);
		}
		return ret;
    }

8、Construct Binary Tree from Preorder and Inorder Traversal

&&

Construct Binary Tree from Inorder and Postorder Traversal

 

两个类型一样,一个是根据先序遍历和中序遍历构造二叉树,一个是根据中序和后序构建二叉树。

1、先序和中序是根据先序的首个元素定位中序的左右子树,然后divided and conquer。

2、相似,根据后序最后一个元素定位中序的左右子树,然后divided and conquer。

构造函数返回结点指针,还是一个递归的方式,将先序中序后序的起始位置和长度参数输入.下列代码,1,2处不同。

TreeNode *buildTree(vector<int> &preorder, vector<int> &inorder) {
        if(preorder.size()<=0){
            return NULL;
        }
        return getNode(0,0,inorder.size(),preorder,inorder);
    }
	TreeNode *getNode(int pstart,int istart,int length,vector<int> &preorder,vector<int> &inorder){
		if(length<=0||pstart+length>preorder.size()||istart+length>inorder.size()){
			return NULL;
		}
		if(length == 1){
			TreeNode * node = new TreeNode(inorder[istart]);
			return node;
		}
		int mid = 0;
		for(int i = 0;i<length;i++){
			if(inorder[istart+i]==preorder[pstart]){//-----------------------------------------1
				mid = istart+i;
				break;
			}
		}
		int left = mid-istart;
		int right = istart+length-mid-1;
		TreeNode * node = new TreeNode(preorder[pstart]);
		node->left = getNode(pstart+1,istart,left,preorder,inorder);
		node->right = getNode(pstart+left+1,mid+1,right,preorder,inorder);
		return node;
	}
TreeNode *buildTree(vector<int> &inorder, vector<int> &postorder) {
        if(inorder.size()<=0){
            return NULL;
        }
        return getNode(0,0,inorder.size(),inorder,postorder);
    }
	TreeNode *getNode(int istart,int pstart,int length,vector<int> &inorder,vector<int> &postorder){
		if(length<=0||istart+length>inorder.size()||pstart+length>postorder.size()){
			return NULL;
		}
		if(length == 1){
			TreeNode * node = new TreeNode(inorder[istart]);
			return node;
		}
		int mid = 0;
		for(int i = 0;i<length;i++){
			if(inorder[istart+i]==postorder[pstart+length-1]){<span style="font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif;">//-----------------------------------------2</span>

				mid = istart+i;
				break;
			}
		}
		int left = mid-istart;
		int right = istart+length-mid-1;
		TreeNode * node = new TreeNode(postorder[pstart+length-1]);
		node->left = getNode(istart,pstart,left,inorder,postorder);
		node->right = getNode(mid+1,pstart+left,right,inorder,postorder);
		return node;
	}
9、Binary Tree Zigzag Level Order Traversal

Given a binary tree, return the zigzag level order traversal of its nodes' values. (ie, from left to right, then right to left for the next level and alternate between).

For example:
Given binary tree {3,9,20,#,#,15,7},

    3
   / \
  9  20
    /  \
   15   7

return its zigzag level order traversal as:

[
  [3],
  [20,9],
  [15,7]
]
其实这个题目和上面分层的差不多,但是zigzag作为一种不同于上述的算法,可以单独拿出来,因为在其他算法中也需要zigzag的方案。

想法一:最直观的想法,构造一个队列和一个栈,奇数层队列输出,偶数层栈输出

看了一下当时我的想法,似乎想法一还是欠妥,我当时的想法是,做两个栈,主要是因为从前往后和从后往前,先左孩子还是先右孩子,需要考虑。

vector<vector<int> > ret;
		ret.clear();
		if(root == NULL){
			return ret;
		}
		stack<TreeNode*> left;
		stack<TreeNode*> right;
		right.push(root);
		while(!left.empty()||!right.empty()){
			vector<int> tmp;
			if(left.empty()){
				while(!right.empty()){
				    if(right.top()->left!=NULL){
				        left.push(right.top()->left);//从左孩子,到右孩子
				        
				    }
					if(right.top()->right!=NULL){
				        left.push(right.top()->right);
				    }
					tmp.push_back(right.top()->val);
					right.pop();
				}
			}
			else{
				while(!left.empty()){
				    if(left.top()->right!=NULL){//从右孩子,到左孩子。
				        right.push(left.top()->right);
				    }
					if(left.top()->left!=NULL){
					    right.push(left.top()->left);
					    
					}
					tmp.push_back(left.top()->val);
					left.pop();
				}
			}
			ret.push_back(tmp);
		}
		return ret;
    }

10、Symmetric Tree

 
剑指offer上面有一个类似的。。。

Given a binary tree, check whether it is a mirror of itself (ie, symmetric around its center).

For example, this binary tree is symmetric:

    1
   / \
  2   2
 / \ / \
3  4 4  3

But the following is not:

    1
   / \
  2   2
   \   \
   3    3

Note:
Bonus points if you could solve it both recursively and iteratively.

没想法,还是没想法。。。记得当时也是尝试用额外空间来做的,因为明知道这个递归是可以做的,基本上大部分的树型的数据结构都可以递归尝试解决下。但是没有构造好结构。

但是看了当时,不知道从哪里看的解法,其实深入一步想一下,还是可以解决的。还是将映射的左右孩子作为参数传入结构题。

bool isSymmetric(TreeNode *root) {

		if(root==NULL||(root->left==NULL&root->right==NULL)){
			return true;
		}
		return istrue(root->right,root->left);
    }
	bool istrue(TreeNode *right,TreeNode *left){
		if(right == NULL&&left==NULL){
			return true;
		}
		if(right == NULL||left == NULL){
			return false;
		}
		return right->val == left->val &&istrue(right->right,left->left)&&istrue(right->left,left->right);
	}


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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值