leetcode刷题笔录-3
13.三角形
- 给出一个“三角形”,找到从底边到顶点的最小路径(即,路径上所有元素加和最小)。路径只能跨越相邻的点。如给出:
[2], [3,4], [6,5,7], [4,1,8,3]
那么就返回11,因为最短路径1-5-3-2的和为11。
- 思路:很简单,与算法导论中一道“国际象棋”棋盘的题很类似。从底边开始生成到每个点的最小路径加和。
- 实现:
class Solution { public: int minimumTotal(vector<vector<int> > &triangle) { int n = triangle.size(); vector<vector<int>> sum(triangle); for(int i=n-2; i>=0; i--){ for (int j=0; j<=i; j++){ sum[i][j] += sum[i+1][j]<sum[i+1][j+1] ? sum[i+1][j] : sum[i+1][j+1]; } } return sum[0][0]; } };
14.帕斯卡三角形
- 给出nRows,生成帕斯卡三角形。如给出nRows=5,则返回:
[ [1], [1,1], [1,2,1], [1,3,3,1], [1,4,6,4,1] ]
- 思路:简单,过。
- 实现:
class Solution { public: vector<vector<int> > generate(int numRows) { vector<vector<int>> triangle; for (int i=0; i<=numRows-1; i++){ vector<int> row; if (i==0){ row = vector<int>(1,1); } else{ for (int j=0; j<=i; j++){ if (j==0) { row.push_back(triangle[i-1][j]); } else if (j==i) { row.push_back(triangle[i-1][j-1]); } else{ row.push_back(triangle[i-1][j-1]+triangle[i-1][j]); } } } triangle.push_back(row); } return triangle; } };
15.帕斯卡三角形2
- 给出索引值k,返回帕斯卡三角形中的第k行。如给出k=3,则返回[1,3,3,1]。只允许使用O(k)的额外空间。
- 思路:也很简单,因为计算每一行只需要用到上一行的值,而跟上一行之上没有关系。所以只需要维护三角形中至多两行,空间消耗为O(2k)=O(k)。
- 实现:
class Solution { public: vector<int> getRow(int rowIndex) { vector<int> tmp; vector<int> current; for (int i=0; i<=rowIndex; i++){ current = vector<int>(); if (i==0){ current.push_back(1); } else{ for(int j=0; j<=i; j++){ if (j==0 || j==i){ current.push_back(1); } else{ current.push_back(tmp[j-1]+tmp[j]); } } } tmp = current; } return current; } };
16.下一个右节点
- 给出一个最简单的二叉树,树的节点有一个额外的域next(见代码注释),指向相同深度节点中右边一个节点,如果已经是同一深度最右的节点了,那么next域则为NULL。现在的二叉树中所有节点next域都为NULL,处理该二叉树使得其具有上述性质。在这个问题中,假设二叉树是完整的(所有叶子节点在同一深度)。比如给出:
1 / \ 2 3 / \ / \ 4 5 6 7
则返回:
1 -> NULL / \ 2 -> 3 -> NULL / \ / \ 4->5->6->7 -> NULL
- 思路:正常的进行前序遍历,对每一个节点:
- 使K的左子结点next域指向K的右子结点
- 使K的右子结点指向K的next节点的左子节点
- 注意我们使用的是前序遍历,这说明在处理K节点的左子结点和右子结点时,我们已经处理了K节点的父节点的左子结点和右子结点(这就包括K),K节点的next域已经指向了应该指向的位置。
- 实现:
/** * Definition for binary tree with next pointer. * struct TreeLinkNode { * int val; * TreeLinkNode *left, *right, *next; * TreeLinkNode(int x) : val(x), left(NULL), right(NULL), next(NULL) {} * }; */ class Solution { public: void connect(TreeLinkNode *root) { if (root == NULL){ return; } if (root->left != NULL && root->right != NULL){ root->left->next = root->right; root->right->next = root->next==NULL ? NULL : root->next->left; } connect(root->left); connect(root->right); } };
17.下一个右节点2
- 同上一题,但此时二叉树不再是完整的了。同时,要求仅使用常量规模的额外存储空间。如,给出:
1 / \ 2 3 / \ \ 4 5 7
应当返回:
1 -> NULL / \ 2 -> 3 -> NULL / \ \ 4-> 5 -> 7 -> NULL
- 思路:由于只能使用常量规模的额外空间了,所以不使用递归而使用循环遍历。节点的next域使我们的按行遍历变得很方便(这种广度优先遍历本来是需要队列支持的)。在实现中,按照行遍历二叉树,当处理某个节点的子节点时,该节点所在的行都已经被next指针连接起来了。根据这篇博文的思路:
- 方法getNext(node)的作用是:返回节点的左节点,如果没有就返回其右节点,如果还没有就返回其next(同一行右侧节点)节点的左节点,其右节点……依此类推。
- 这个方法有两个作用:
- 当前行处理完成之后,根据当前行的首节点(我们使用它来维持外部循环),寻找下一行的首节点:如果首节点有左节点,那下一行的首节点就是左节点,没有,则下一行的首节点就是右节点。如果当前行首节点是叶子节点,那么下一行的首节点就是next节点的左节点,右节点……依此类推。
- 处理当前节点(我们用它来维持外部循环)的右节点时,或者处理当前节点的左节点且当前节点没有右节点时,那么next指针就需要指向当前节点的next节点的左节点,右节点(如果没有左节点)……依此类推。
- 实现:
/** * Definition for binary tree with next pointer. * struct TreeLinkNode { * int val; * TreeLinkNode *left, *right, *next; * TreeLinkNode(int x) : val(x), left(NULL), right(NULL), next(NULL) {} * }; */ class Solution { public: void connect(TreeLinkNode *root) { if (root==NULL){ return; } TreeLinkNode* lineHead = root; TreeLinkNode* node = root; while(lineHead){ node = lineHead; while(node){ conectChildren(node); node = node->next; } lineHead = getNext(lineHead); } } private: void conectChildren(TreeLinkNode* node){ // Consider node->left if (node->left != NULL){ if (node->right!=NULL){ node->left->next = node->right; } else{ node->left->next = getNext(node->next); } } // Consider node->right if (node->right != NULL){ node->right->next = getNext(node->next); } } TreeLinkNode* getNext(TreeLinkNode* node){ if (node == NULL){ return NULL; } else if (node->left != NULL){ return node->left; } else if (node->right != NULL){ return node->right; } else{ return getNext(node->next); } } };
作者:一叶斋主人 出处:www.cnblogs.com/yiyezhai 本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。