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

1、Palindrome Partitioning && Palindrome Partitioning II

Given a string s, partition s such that every substring of the partition is a palindrome.

Return all possible palindrome partitioning of s.

For example, given s = "aab",
Return

  [
    ["aa","b"],
    ["a","a","b"]
  ]

题意,就是将字符串的所有回文列出来,中间分割开而已。

一开始想着用动态规划,但是动态规划,又没有想到好的想法,动态规划似乎不合适,毕竟上一次的i的不能给i+1的字符串来用,但是其实自己想的太少,其实是可以用的。把i,j之间的字符串是否回文。这样下一次,对,i-1到j+1之间的是有用的,这也就利用了动态规划的思想。

class Solution {
private:
	vector<vector<string>> spath;
public:
    vector<vector<string>> partition(string s) {
        int i = 0;
		vector<string> path;
		string temp = "";
		ispali(path,temp,s);
		return spath;
    }
	void ispali(vector<string>path,string str,string s){
		if(str.length()>0){
			path.push_back(str);
		}
		int length = 1;
		for(int i = 0;i<s.length();){
			if(i+length-1<s.length()){
				if(pali(s.substr(i,length))){
					if(i+length >= s.length()){
						path.push_back(s.substr(i,length));
						spath.push_back(path);
						break;
					}
					else{
						ispali(path,s.substr(i,length),s.substr(i+length,s.length()-i-length));
					}
				}
				length++;
			}
			else{
				break;
			}
		}
	}
	bool pali(string s){
		if(s.length()==1){
			return true;
		}
		for(int i=0;i<s.length()/2;i++){
			if(s[i]!=s[s.length()-1-i]){
				return false;
			}
		}
		return true;
	}
};

Given a string s, partition s such that every substring of the partition is a palindrome.
Return the minimum cuts needed for a palindrome partitioning of s.
For example, given s = "aab",
Return 1 since the palindrome partitioning ["aa","b"] could be produced using 1 cut.
这个是求回文分割的最小分割次数,似乎用上面的方法也是可以的,因为毕竟你是可以得到最终分割次数的嘛。不过复杂度就多了,因为动态规划是从1个字符开始的,所以对于这个问题来说做了很多无用功。

这里用了另外一个方案,就是i,j表示i,j是否是回文,这样添加一个字符I以后,就可以得出,i,j+1之间的回文数量等于,i到j+1之间是否是回文,或者i+j之间回文数量+1,从j出分割开。其实发现,用vector的效率是低于指针类型的,所以尽量用指针吧。

class Solution {
public:
     int minCut(string s) {
		/*
		用一个数组p[i][j]表示,i,j是否是回文.
		f(i)表示,i到len所需要的mincut,返回f(0),子问题是,i+1到len之间的mincut数,是一个有用的信息,而我们所需要做的就是在
		添加上一个第i个字符,然后计算i到len之间的mincut数,将i和len之间所有的j遍历,查看i到j,和(f(j+1))j+1到mincut的所有最小值。
		f(i) = min(f(i),f(j+1)+1),len>j>=i,且p(i,j)为回文,遍历i和len之间的所有j
		*/
		int len = s.length();
		int i,j;
		int *Min = new int[len+1];
		for(i = 0; i <= len; i++)   
            Min[i] = len-i;  //从后往前定义mincut
		bool ** P = new bool*[len];//表示i,j之间是否是回文
		
		for(i=0;i<len;i++){
			P[i] = new bool[len];
			for(j=0;j<len;j++){
				P[i][j] = false;
			}
		}
		for(i = len-1;i>=0;i--){
			for(j = i;j<len;j++){
				if(s[i]==s[j]&&(j-i<2||P[i+1][j-1])){
					P[i][j]=true;
					Min[i] = min(Min[i],Min[j+1]+1);
				}
			}
		}
		int ret = Min[0]-1;
		for(i=0;i<len;i++){
			delete P[i];
		}
		delete Min;
		delete P;
		return ret;
    }
};

2、Surrounded Regions

 

Given a 2D board containing 'X' and 'O', capture all regions surrounded by 'X'.

A region is captured by flipping all 'O's into 'X's in that surrounded region.

For example,

X X X X
X O O X
X X O X
X O X X

After running your function, the board should be:

X X X X
X X X X
X X X X
X O X X
这道题,按自己之前的思路,真是死的一片糊涂啊,过了好多次都没有过。这个leetcode上通过率14%

之前的思路,遍历board的四周一圈,然后将有o的地方进行DFS进行搜索,然后将o替换为#,这样后面这些#再替换为x,没有遍历到的就自然是o了。但是是错误的,代码贴出来

错误的,有点长,但是原理还好懂的。。。。第一个就不能针对只有一个o的这种情况。

class Solution {  
private:
	int lenx;
	int leny;
public:
    void solve(vector<vector<char>> &board) {
		lenx = board.size();
		if(lenx<=0){
			return ;
		}
		leny = board[0].size();
		if(leny<=0){
			return;
		}
		for(int i = 0;i<leny;i++){
			if(board[0][i] == 'o'){
				ChangeState(0,board,0,i);//从上到下
			}
			if(board[lenx-1][i] == 'o'){
				ChangeState(3,board,lenx-1,i);//从下道上
			}
			
		}
		for(int j = 0;j<lenx;j++){
			if(board[j][0] == 'o'){
				ChangeState(1,board,j,0);//从左到右
			}
			if(board[j][leny-1] == 'o'){	
				ChangeState(2,board,j,leny-1);//从右到左
			}
		}
		for(int i = 0;i<lenx;i++){
			for(int j = 0;j<leny;j++){
				if(board[i][j] == '#'){
					board[i][j] = 'o';
				}
				else{
					board[i][j] = 'X';
				}
			}
		}
    }
	void ChangeState(int direct,vector<vector<char>> &board,int i,int j){
		if(i<0||j<0||i>=lenx||j>=leny){
			return;
		}
		if(board[i][j] != 'o'){
			return;
		}
		else{
			board[i][j] = '#';
			if(direct == 0){//从上到下
				ChangeState(0,board,i+1,j);
				ChangeState(0,board,i,j+1);
				ChangeState(0,board,i,j-1);
			}
			else if(direct == 1){//从左到右
				ChangeState(1,board,i,j+1);
				ChangeState(1,board,i+1,j);
				ChangeState(1,board,i-1,j);
			}
			else if(direct == 2){//从右到左
				ChangeState(2,board,i,j-1);
				ChangeState(2,board,i+1,j);
				ChangeState(2,board,i-1,j);
			}
			else if(direct == 3){//从下倒上
				ChangeState(3,board,i,j-1);
				ChangeState(3,board,i,j+1);
				ChangeState(3,board,i-1,j);
			}
			
		}
	}
};  
然后正确的也说一下,原理是加了一个queue,但是我感觉原理差不多啊。可能主要在于,我在处理方向的问题上除了问题,我用了一个比较蠢的方法,分了方向,所以

class Solution {
public:
    queue<int> q;
    int m, n;
    
    void add(int x, int y, vector<vector<char>> &board) {
        if (x >= 0 && x < m && y >= 0 && y < n && board[x][y] == 'O') {
            board[x][y] = 'Z';
            q.push(x * n + y);
        }    
    }
    
    void traversal(int x, int y, vector<vector<char>> &board) {
        add(x, y, board);
        while (!q.empty()) {
            int p = q.front();
            q.pop();            
            int px = p / n, py = p % n;
            add(px - 1, py, board);
            add(px + 1, py, board);
            add(px, py - 1, board);
            add(px, py + 1, board);
        }
    }
    
    void solve(vector<vector<char>> &board) {
        // Start typing your C/C++ solution below
        // DO NOT write int main() function
        if (board.empty() || board.size() == 0 || board[0].size() == 0) {
            return;
        }
        m = board.size(), n = board[0].size();
        for (int i = 0; i < n; i++) {
            traversal(0, i, board);
            traversal(m - 1, i, board);
        }
        for (int i = 0; i < m; i++) {
            traversal(i, 0, board);
            traversal(i, n - 1, board);
        }
        for (int i = 0; i < m; i++) {
            for (int j = 0; j < n; j++) {
                board[i][j] = board[i][j] == 'Z' ? 'O' : 'X';
            }
        }
    }
};

3、Sum Root to Leaf Numbers

 

Given a binary tree containing digits from 0-9 only, each root-to-leaf path could represent a number.

An example is the root-to-leaf path 1->2->3 which represents the number 123.

Find the total sum of all root-to-leaf numbers.

For example,

    1
   / \
  2   3
The root-to-leaf path 1->2 represents the number 12.
The root-to-leaf path 1->3 represents the number 13.

Return the sum = 12 + 13 = 25.
/**
 * Definition for binary tree
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode(int x) : val(x), left(NULL), right(NULL) {}
 * };
 */
class Solution {
public:
	int sum;
    int sumNumbers(TreeNode *root) {
        sum = 0;
		Sum(root,0);
		return sum;
    }
	void Sum(TreeNode * root,int tempsum){
		if(root == NULL){
			return;
		}
		if(root->left == NULL&&root->right == NULL){//叶子结点
			tempsum = tempsum*10+root->val;
			sum+=tempsum;
		}
		Sum(root->left,tempsum*10+root->val);
		Sum(root->right,tempsum*10+root->val);
	}
};

原理就是树的遍历,这里是先序遍历。。。

4、Longest Consecutive Sequence

Given an unsorted array of integers, find the length of the longest consecutive elements sequence.

For example,
Given [100, 4, 200, 1, 3, 2],
The longest consecutive elements sequence is [1, 2, 3, 4]. Return its length: 4.

Your algorithm should run in O(n) complexity.
一开始想成了,之前遇到的,连续正整数的题目缺失哪一个数字,那个题目最终要做的是申请一个空间,存入数就可以了。

这个题目不是,找到连续数字,最长。利用unordered_set数据结构,这个是C++中存储hash值的,不同于unordered_map是键值对,这个只有值。

存储了数据以后,然后在从头开始遍历数据,然后两个操作,与从这个数往前寻找连续数,一个往后寻找连续数,一遍找一遍删除

知道找到最大的连续子数列最长值。

int longestConsecutive(vector<int> &num) {
		if(num.size()<=1){
			return num.size();
		}
		unordered_set<int> hashset;
		for(int i=0;i<num.size();i++){
			hashset.insert(num[i]);
		}
		int ret = 1;
		while(!hashset.empty()){
			int v = *hashset.begin();
			hashset.erase(v);
			int back = 0,front = 0,v1 = v-1,v2 = v+1;
			while(hashset.find(v1)!=hashset.end()){//往前
				hashset.erase(v1);
				v1--;
				back++;
			}
			while(hashset.find(v2)!=hashset.end()){//往后
				hashset.erase(v2);
				v2++;
				front++;
			}
			int length = back+front+1;
			ret = (ret>length)?ret:length;
		}
		return ret;
	}
5、Word Ladder  && II

Given two words (start and end), and a dictionary, find the length of shortest transformation sequence from start to end, such that:

  1. Only one letter can be changed at a time
  2. Each intermediate word must exist in the dictionary

For example,

Given:
start = "hit"
end = "cog"
dict = ["hot","dot","dog","lot","log"]

As one shortest transformation is "hit" -> "hot" -> "dot" -> "dog" -> "cog",
return its length 5.

Note:

  • Return 0 if there is no such transformation sequence.
  • All words have the same length.
  • All words contain only lowercase alphabetic characters.
这两个有点难,而且特别复杂。

这里直说原理了,这个是700多ms过的leetcode,但是真心觉得算法不好,如果遇到好的,贴过来,研究下。

原理:先将start能一次transe的所有单词加入队列,然后再取队列的单词继续找他的一次可以达到的单词,加入队列,这样最终就类似于    start ----word1,word1,word1,。。。------word2,word2,word2,。。---end

复杂度如果不考虑单词的长度,其实就是单词的一个洪泛遍历了。。。就类似于社交网络的查找一样,A,找A的所有好友,A的所有好友找好友的好友。。。一直往下找,这里不会重复,因为遍历经过就删除了。

int ladderLength(string start, string end, unordered_set<string> &dict) {
        int min;

		queue<string> q;
		q.push(start);
		min = 1;
		while(!q.empty()){
			min++;
			int len = q.size();
			while(len>0){
				len --;
				string node(q.front());
				q.pop();
				
				for(int i = 0;i<node.size();i++){
					string str = node;
					for(char j='a';j<='z';j++){
						str[i] = j;
						if(str == node){
							continue;
						}
						if(dict.count(str)){
							q.push(str);
							dict.erase(str);
						}
						if(str == end){
							return min;
						}
					}
					
				}
			}
			
		}
		return 0;
    }

Given two words (start and end), and a dictionary, find all shortest transformation sequence(s) from start to end, such that:

  1. Only one letter can be changed at a time
  2. Each intermediate word must exist in the dictionary

For example,

Given:
start = "hit"
end = "cog"
dict = ["hot","dot","dog","lot","log"]

Return

  [
    ["hit","hot","dot","dog","cog"],
    ["hit","hot","lot","log","cog"]
  ]

Note:

  • All words have the same length.
  • All words contain only lowercase alphabetic characters.
这是另外一个题目,这次是找到所有的最短路径,这样上面的那个算法就没有用处了,因为上面的算法在中途将单词都删除掉了。
 
好累,11点半了,睡觉去了。。这个题目先贴在这里
<pre name="code" class="cpp">class Solution {
public:
/*
使用了一个前驱单词表,即记录每一个单词的前驱单词是哪些。这样在遍历完毕后,我们从end出发递归就能把所有路径生成出来。但是由于前驱单词表不能记录当前的层次信息,似乎我们没法完成去重的工作。这个方案的巧妙之处就在于它没有使用我们通常的队列保存待处理的单词,一个单词一个单词先进先出处理的方法,而是使用两个vector来模拟队列的操作。我们从vector 1中遍历单词进行转换尝试,发现能转换的单词后将其放入vector 2中。当vector 1中的单词处理完毕后即为一层处理完毕,它里面的单词就可以从字典里删去了。接着我们对vector 2进行同样处理,如此反复直到当前处理的vector中不再有单词。我们发现vector 1和vector 2在不断地交换正处理容器和待处理容器的身份,因此可以通过将其放入一个数组中,每次循环对数组下标值取反实现身份的交替.
*/
    vector<vector<string>> result; 
	vector<vector<string>> findLadders(string start, string end, unordered_set<string> &dict) {
		result.clear();
		unordered_map<string, vector<string>> prevMap;
		for(auto iter = dict.begin(); iter != dict.end(); ++iter)  
            prevMap[*iter] = vector<string>(); 
		vector<unordered_set<string>> candidates(2);
		int current = 0;  
        int previous = 1;  
        candidates[current].insert(start);
		while(true)  
		{
			current = !current;  
            previous = !previous;  
            for (auto iter = candidates[previous].begin(); iter != candidates[previous].end(); ++iter)  
                dict.erase(*iter); 
			candidates[current].clear();
			for(auto iter = candidates[previous].begin(); iter != candidates[previous].end(); ++iter)  
            {  
                for(size_t pos = 0; pos < iter->size(); ++pos)  
                {  
                    string word = *iter;  
                    for(int i = 'a'; i <= 'z'; ++i)  
                    {  
                        if(word[pos] == i)continue;  
                        word[pos] = i;  
                        if(dict.count(word) > 0)  
                        {  
                            prevMap[word].push_back(*iter);  
                            candidates[current].insert(word);  
                        }  
                    }  
                }  
            } 
			if(candidates[current].size() == 0)  
                return result;  
			if (candidates[current].count(end)) break; 
		}
		

		vector<string> path;  
        GeneratePath(prevMap, path, end);  
        return result; 
	}
	void GeneratePath(unordered_map<string, vector<string>> &prevMap, vector<string>& path, const string& word)  
	{  
		if (prevMap[word].size() == 0)  
		{  
			path.push_back(word);
			vector<string> curPath = path; 
			reverse(curPath.begin(), curPath.end()); 
			result.push_back(curPath);  
			path.pop_back();
			return; 
		}
		path.push_back(word);
		for (auto iter = prevMap[word].begin(); iter != prevMap[word].end(); ++iter)  
            GeneratePath(prevMap, path, *iter);  
        path.pop_back(); 
	}
};
 

6、Valid Palindrome

 Given a string, determine if it is a palindrome, considering only alphanumeric characters and ignoring cases.For example,"A man, a plan, a canal: Panama" is a palindrome."race a car" is not a palindrome.Note:Have you consider that the string might be empty? This is a good question to ask during an interview.For the purpose of this problem, we define empty string as valid palindrome.

原理很简单,就是将不是字符和数字的去掉,然后查看头和尾的两个结点是否相差32,这个也是大些和小写的差值,如果不知道,其实可以用A-a表示

bool isPalindrome(string s) {
        if(s.size()<=1){
			return true;
		}
		int start = 0;
		int end = s.length()-1;
		while(start<end){
			while(start<end&&!((s[start]>='0'&&s[start]<='9')||(s[start]>='A'&&s[start]<='Z')||(s[start]<='z'&&s[start]>='a'))){
				start++;
			}
			while(start<end&&!((s[end]>='0'&&s[end]<='9')||(s[end]>='A'&&s[end]<='Z')||(s[end]<='z'&&s[end]>='a'))){
				end--;
			}
			if(s[end]!=s[start]&&(abs(s[end]-s[start]))!=32){
				return false;
			}
			start++;
			end--;
		}
		return true;
    }

8、Binary Tree Maximum Path Sum

 

Given a binary tree, find the maximum path sum.

The path may start and end at any node in the tree.

For example:
Given the below binary tree,

       1
      / \
     2   3

Return 6.

这个题目考虑的可能是,这个数值可能是以树中某一个非页结点开始的,不一定限定在root结点。

递归的方式,查找结点的左支线的最大值,和右支线的最大值,两个加起来,和当前最大值相比。需要考虑的是,可能最大值是左线也可能是右线,或者和,有的时候两条直线可能是负数。

int max;
    int maxPathSum(TreeNode *root) {
		max = INT_MIN;
		if(root == NULL){
			return 0;
		}
		int temp = maxPath(root);
		max = (max>temp)?max:temp;
		return max;
    }
	int maxPath(TreeNode *root){
		if(root == NULL){
			return 0;
		}
		int left = maxPath(root->left);
		int right = maxPath(root->right);
		int suml=left+root->val;
		int sumr=right+root->val;
		int sum =left+right+root->val;
		max = (max>suml)?max:suml;
		max = (max>sumr)?max:sumr;
		max = (max>sum)?max:sum;
		if(left>right){
			if(left<0){
				return root->val;
			}
			else{
				return suml;
			}
		}
		else{
			if(right<0){
				return root->val;
			}
			else{
				return sumr;
			}
		}
	}
7、Best Time to Buy and Sell Stock I II III

Say you have an array for which the ith element is the price of a given stock on day i.

If you were only permitted to complete at most one transaction (ie, buy one and sell one share of the stock), design an algorithm to find the maximum profit.

这是第一题,只能买一次,卖一次。所以是寻找极值。

从数组开头起始,往后寻找最小的点,从数组结尾往前寻找最大的点。这两个点的差值是最有可能成为最佳时间购买的时间段。但是需要考虑到,最小值点在最大值的前面,这样就不能进行买入最小点,卖出最小点了。

所以需要考虑到将最初值到最大值点ID的最大值,和最小点ID到结尾的最大值。

三段综合考虑,才最终得到需要找到的值。

int maxProfit(vector<int> &prices) {
		if(prices.size()<=1){
			return 0;
		}
		int max = 0;
		int start = 0;
		int end = prices.size()-1;
		while(start<end){
		    for(int i=start+1;i<=end;i++){
				if(prices[i]>prices[i-1]){
					start = i-1;
					break;
				}
			}//最小的初始点
			for(int i=end-1;i>=start;i--){
				if(prices[i]<prices[i+1]){
					end = i+1;
					break;
				}
			}//最大的结尾点
			if(start>end){
				break;
			}
			int small = prices[start];
			int big = prices[start];
			int smallid = start;
			int bigid = start;
			for(int i = start+1;i<=end;i++){
				if(prices[i]>big){
					big = prices[i];
					bigid = i;
				}
				if(prices[i]<small){
					small = prices[i];
					smallid = i;
				}
			}//查找start和end之间的最小值和最大值
			if(smallid<bigid){
				if(big-small>max){
					max = big-small;//中间一段,第二段的差值
				}
			}
			int s1 = big;
			for(int i = start;i<bigid;i++){
				if(prices[i]<s1){
					s1 = prices[i];
				}
			}//从start到最大值ID,寻找最小值,这是第一段的差值
			if(big - s1>max){
				max = big-s1;
			}
			s1 = small;
			for(int i = smallid+1;i<=end;i++){
				if(prices[i]>s1){
					s1 = prices[i];
				}
			
			}//从最小值ID到end,寻找最大值,这是第三段差值
			if(s1-small>max){
				max = s1-small;
			}
			start = bigid+1;
			end = smallid-1;
		}
		if(max<0){
			return 0;
		}
		return max;
    }

Say you have an array for which the ith element is the price of a given stock on day i.

Design an algorithm to find the maximum profit. You may complete as many transactions as you like (ie, buy one and sell one share of the stock multiple times). However, you may not engage in multiple transactions at the same time (ie, you must sell the stock before you buy again).

这次是可以进行多次买卖,但是只能同一时间买一次 或者卖一次。那么,只要下一个时间比前一个时间的值大就可以了,就可以先买入,再卖出。

int maxProfit(vector<int> &prices) {
        if(prices.size()<=1){
            
            return 0;
        }
        int min = 0;
		int profit = 0;
		for(int i = 0;i<prices.size();i++){
			if(min<prices[i]){
				profit += (prices[i]-min); 
				min = prices[i];
			}
			else{
				min = prices[i];
			}
		}
		return profit-prices[0];
    }

Say you have an array for which the ith element is the price of a given stock on day i.

Design an algorithm to find the maximum profit. You may complete at most two transactions.

Note:
You may not engage in multiple transactions at the same time (ie, you must sell the stock before you buy again).

这个题目是最难的,一个限制了交易次数,只能操作两次。通俗的说是,买入,卖出,买入,卖出。这样就是两个trans,其实时间点上,这是两个时间段,这样就是前一个时间段和后一个时间段进行计算,divided and conquer。

http://blog.unieagle.net/2012/12/05/leetcode%E9%A2%98%E7%9B%AE%EF%BC%9Abest-time-to-buy-and-sell-stock-iii%EF%BC%8C%E4%B8%80%E7%BB%B4%E5%8A%A8%E6%80%81%E8%A7%84%E5%88%92/

看看在prices的子序列[0,...,i][i,...,n-1]上分别取得的最大利润。最后用的是动态规划进行提升。用数组保持i-j之间的最大利润。

int maxProfit(vector<int> &prices) {
		if(prices.size()<=1){
			return 0;
		}
		int len = prices.size();
		vector<int> pre(len);
		vector<int> last(len);
		int max = 0;
		int min = prices[0];
		pre[0] = 0;
		
		for(int i = 1;i<len;i++){
			if(max<prices[i]-min){
				pre[i] = prices[i]-min;
				max = prices[i]-min;
			}
			else{
				pre[i] = max;
			}
			min=(min<prices[i])?min:prices[i];
		}
		int maxprofit = pre[len-1];
		min = prices[len-1];
		max = 0;
		last[len-1] = 0;
		for(int i = len-1;i>=0;i--){
			if(max<min-prices[i]){
				last[i] = min-prices[i];
				max =  min-prices[i];
			}
			else{
				last[i] = max;
			}
			min = (min>prices[i])?min:prices[i];
			if(i-1>=0){
				maxprofit = (maxprofit>(last[i]+pre[i]))?maxprofit:(last[i]+pre[i]);
			}
		}
		return maxprofit;
    
    }
8、

Triangle

 

Given a triangle, find the minimum path sum from top to bottom. Each step you may move to adjacent numbers on the row below.

For example, given the following triangle

[
     [2],
    [3,4],
   [6,5,7],
  [4,1,8,3]
]

The minimum path sum from top to bottom is 11 (i.e., 2 + 3 + 5 + 1 = 11).

Note:
Bonus point if you are able to do this using only O(n) extra space, where n is the total number of rows in the triangle.

动态规划。有些忘记了,刚才看了一下当时写的,其实还是动态规划的思想。将最小值先进行存储。

vec[i]保存到三角形某一行,第i个位置的最小值,这个是中间结果,根据这个中间结果,可以一直计算下一行的数值。

int minimumTotal(vector<vector<int> > &triangle) {
		if(triangle.size()<=0){
			return 0;
		}
		int len = triangle.size();
		vector<int> vec(len);
		for(int i = 0;i<len;i++){
			vec[i] = INT_MAX;
		}
		vec[0] = triangle[0][0];
		for(int i = 1;i<len;i++){
			int next = vec[1];
			int pre = vec[0];
			for(int j = 1;j<i;j++){
				vec[j]=min(next+triangle[i][j],pre+triangle[i][j]);
				pre = next;
				next = vec[j+1];
			}
			vec[0]=vec[0]+triangle[i][0];
			vec[i]=pre+triangle[i][i];
			
		}
		int min=INT_MAX;
		for(int i = 0;i<len;i++){
			if(vec[i]<min){
				min = vec[i];
			}
		}
		return min;
    }

9、Pascal's Triangle I II


Given numRows, generate the first numRows of Pascal's triangle.

For example, given numRows = 5,
Return

[
     [1],
    [1,1],
   [1,2,1],
  [1,3,3,1],
 [1,4,6,4,1]
]
一行一行计算就可以了。。。

vector<vector<int> > generate(int numRows) {
		vector<vector<int> > ret;
		ret.clear();
		if(numRows == 0){
			return ret;
		}
		vector<int> temp;
		temp.push_back(1);
		ret.push_back(temp);
		 for(int i = 1;i<numRows;i++){
			vector<int> mid;
			mid.push_back(1);
			for(int j = 1;j<ret[i-1].size();j++){
				mid.push_back(ret[i-1][j-1]+ret[i-1][j]);
			}
			mid.push_back(1);
			ret.push_back(mid);
		 }
		 return ret;
    }

Given an index k, return the kth row of the Pascal's triangle.

For example, given k = 3,
Return [1,3,3,1].

Note:
Could you optimize your algorithm to use only O(k) extra space?

这个不是输出全部,只是输出某一行,如果按照上面的思路也是可以,不过这里需要一个中间数组进行转换。根据前面的字典转换的例子,根据申请一个2个空间的大小vector进行奇偶变换也是可以的。这是方法一。

另外一个相似的方法,是每次将上次结果作为一个参数输入函数,然后得到本次的结果,一直迭代。不过,我觉得这种方案的速度差一些,必将每次进行申请空间和构造的花费高一些。

vector<int> getRow(int rowIndex) {
		vector<int> ret;
		
		ret.clear();
		if(rowIndex<0){
			return ret;
		}
		ret.push_back(1);
		for(int i = 1;i<rowIndex+1;i++){
			vector<int> tmp(ret);//一直迭代。
			getK(ret,tmp);
		}
		return ret;
    }
	void getK(vector<int>&vec,vector<int>&tmp){//根据上次结果,计算本次的结果
		vec.clear();
		vec.push_back(1);
		for(int i = 1;i<tmp.size();i++){
			vec.push_back(tmp[i-1]+tmp[i]);
		}
		vec.push_back(1);
	}

10、Populating Next Right Pointers in Each Node

 

Given a binary tree

    struct TreeLinkNode {
      TreeLinkNode *left;
      TreeLinkNode *right;
      TreeLinkNode *next;
    }

Populate each next pointer to point to its next right node. If there is no next right node, the next pointer should be set to NULL.

Initially, all next pointers are set to NULL.

Note:

  • You may only use constant extra space.
  • You may assume that it is a perfect binary tree (ie, all leaves are at the same level, and every parent has two children).

For example,
Given the following perfect binary tree,

         1
       /  \
      2    3
     / \  / \
    4  5  6  7

After calling your function, the tree should look like:

         1 -> NULL
       /  \
      2 -> 3 -> NULL
     / \  / \
    4->5->6->7 -> NULL
只要将上一层的制作成链表,下一层,则就可以根据左孩子,右孩子这些来做了。

void connect(TreeLinkNode *root) {
		TreeLinkNode*pleft = root;
		while(pleft != NULL){
			TreeLinkNode*cur = pleft;
			pleft = pleft->left;
			while(cur!=NULL){
			    if(cur->left!=NULL){
			        cur->left->next=cur->right;
			    }
				
				if(cur->next!=NULL){
				    if(cur->right!=NULL){
    			                 cur->right->next=cur->next->left;
    			            }
				}
				cur = cur->next;
			}
		}
    }

Follow up for problem "Populating Next Right Pointers in Each Node".

What if the given tree could be any binary tree? Would your previous solution still work?

Note:

  • You may only use constant extra space.

For example,
Given the following binary tree,

         1
       /  \
      2    3
     / \    \
    4   5    7

After calling your function, the tree should look like:

         1 -> NULL
       /  \
      2 -> 3 -> NULL
     / \    \
    4-> 5 -> 7 -> NULL

一个道理

void connect(TreeLinkNode *root) {
		TreeLinkNode*pleft = root;
		while(pleft != NULL){
			TreeLinkNode*cur = pleft;
			while(pleft!=NULL&&pleft->left==NULL&&pleft->right == NULL){
				pleft = pleft->next;
			}//寻找下一个,处理其左右孩子
			if(pleft!=NULL){//下一层接收处理的首个结点
			    if(pleft->left!=NULL){
			       pleft = pleft->left; 
			    }
			    else{
			        pleft = pleft->right; 
			    }
			}//将指针定位下一层的做孩子或者右孩子//下面是这一层的处理过程
			while(cur!=NULL){
			    if(cur->left!=NULL){
			        cur->left->next=cur->right;// ----------------》1
			    }
				TreeLinkNode*pnext = cur->next;
				while(pnext!=NULL&&pnext->left==NULL&&pnext->right == NULL){
				    pnext = pnext->next;
				}//寻找下一个有做孩子或者右孩子的点
				if(pnext!=NULL){
				    if(cur->right!=NULL){//当前结点有右孩子,则1是正确的,则处理right结点
				        if(pnext->left!=NULL){
				            cur->right->next=pnext->left;
				        }
				        else{
				            cur->right->next=pnext->right;
				            
				        }
    			        
    			    <span style="white-space:pre">		</span>}
    			    <span style="white-space:pre">	</span>     else if(cur->left!=NULL){//做孩子不为空,但是右孩子为空
    			       <span style="white-space:pre">		</span>if(pnext->left!=NULL){
				            <span style="white-space:pre">	</span>cur->left->next=pnext->left;
				        }
				        else{
				                cur->left->next=pnext->right;
				        }
    			    <span style="white-space:pre">	</span>        }
				}
				cur = pnext;//下一个处理的
			}
		}
    }

2014-10-11








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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值