leetcode -day11 Clone Graph & Palindrome Partitioning I II
2014-05-08 22:18
423 查看
1、Clone Graph
Clone an undirected graph. Each node in the graph contains a
a list of its
OJ's undirected graph serialization:
Nodes are labeled uniquely.
We use
a separator for node label and each neighbor of the node.
As an example, consider the serialized graph
The graph has a total of three nodes, and therefore contains three parts as separated by
First node is labeled as
Connect node
both nodes
Second node is labeled as
Connect node
node
Third node is labeled as
Connect node
node
thus forming a self-cycle.
Visually, the graph looks like the following:
分析:复制图,乍一看挺像复制有随机指针的链表的,复制随机链表是三步进行的,图不能采用此种方法,但是可以借鉴,可以先深度遍历,相当于先复制所有节点,再复制邻居指针,采用递归的形式进行深度遍历。复制邻居指针时,需要判断邻居结点是否已经访问过,而结点的label是唯一的,可以采用map来保存。同时注意当map中值为指针时,key存在用下标进行访问时,map[key]也为空,采用map.find(key)!=map.end()来进行判断表中是否已经保存。
代码如下:
2、Palindrome Partitioning
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 =
Return
分析:输出一个字符串的所有可划分为回文的可能,采用递归的手法,依次判断前i个是否是回文,并递归判断后续的。
代码如下:
3、Palindrome Partitioning II
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 =
Return
be produced using 1 cut.
分析:初步分析,根据上题稍加修改,就能计算出来最小分割数,但是一直出现超时的问题。递归耗时太多,超时的代码如下:
Status:
改进,分析上述超时的原因,有两个方面,第一采用递归而不是循环的方式耗时多,第二在判断字串是否是回文串时,采用遍历操作,很多子问题重复求解。
有了原因的分析,来改进,对于第二个判断字串是否是回文串时,采用动态规划的问题,如判断一个字符串位置i到j的字串是否为回文串,如果i和j相同则只有一个字符,为真;如果s[i]==s[j],则和字符串位置i+1到j-1的分析相同.为了避免多次重复计算,保存各个位置到另外位置的回文串标志。
对于第一个问题,也可以采用动态规划的方法,计算从0位置开始到i位置的分割数,如果0到i字符串就是一个回文串则分割数为0;如果不是,则从0-i开始依次判断其中j到i位置是否是回文串,如果是就是从0位置开始到j位置的分割数+1,得到的最小值为此时要求的分个数。其实思想和上题是一样的。
代码如下:(边界问题处理了好久,一定不要下标越界)
Accepted
1、Clone Graph
Clone an undirected graph. Each node in the graph contains a
labeland
a list of its
neighbors.
OJ's undirected graph serialization:
Nodes are labeled uniquely.
We use
#as a separator for each node, and
,as
a separator for node label and each neighbor of the node.
As an example, consider the serialized graph
{0,1,2#1,2#2,2}.
The graph has a total of three nodes, and therefore contains three parts as separated by
#.
First node is labeled as
0.
Connect node
0to
both nodes
1and
2.
Second node is labeled as
1.
Connect node
1to
node
2.
Third node is labeled as
2.
Connect node
2to
node
2(itself),
thus forming a self-cycle.
Visually, the graph looks like the following:
1 / \ / \ 0 --- 2 / \ \_/
分析:复制图,乍一看挺像复制有随机指针的链表的,复制随机链表是三步进行的,图不能采用此种方法,但是可以借鉴,可以先深度遍历,相当于先复制所有节点,再复制邻居指针,采用递归的形式进行深度遍历。复制邻居指针时,需要判断邻居结点是否已经访问过,而结点的label是唯一的,可以采用map来保存。同时注意当map中值为指针时,key存在用下标进行访问时,map[key]也为空,采用map.find(key)!=map.end()来进行判断表中是否已经保存。
代码如下:
class Solution { public: UndirectedGraphNode *cloneGraph(UndirectedGraphNode *node) { if(node==NULL){ return NULL; } unordered_map<int,UndirectedGraphNode*> labelNodeMap; return cloneGraphRecursive(node,labelNodeMap); } UndirectedGraphNode *cloneGraphRecursive(UndirectedGraphNode *node,unordered_map<int,UndirectedGraphNode*>& labelNodeMap) { if(labelNodeMap.find(node->label) != labelNodeMap.end()){ return labelNodeMap[node->label]; } UndirectedGraphNode* clonedNode = new UndirectedGraphNode(node->label); labelNodeMap.insert(make_pair(node->label,clonedNode)); for(int i=0; i< node->neighbors.size(); ++i){ UndirectedGraphNode* neighborNode = cloneGraphRecursive(node->neighbors[i],labelNodeMap); clonedNode->neighbors.push_back(neighborNode); } return clonedNode; } };
2、Palindrome Partitioning
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个是否是回文,并递归判断后续的。
代码如下:
class Solution { public: vector<vector<string>> partition(string s) { vector<string> strVec; partitionCore(s,strVec); return allPartition; } void partitionCore(string s,vector<string>& strVec){ int length = s.length(); if(s.empty()){ allPartition.push_back(strVec); return; } for(int i=1; i<=length; ++i){ string subStr = s.substr(0,i); if(isPalindrome(subStr)){ strVec.push_back(subStr); string leftSubStr = s.substr(i,length-i); partitionCore(leftSubStr,strVec); strVec.pop_back(); } } } bool isPalindrome(string s){ int length = s.length(); if(length == 1){ return true; } int begin = 0; int end = length-1; while(begin <= end){ if(s[begin]!=s[end]){ return false; } ++begin; --end; } return true; } vector<vector<string>> allPartition; };
3、Palindrome Partitioning II
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
1since the palindrome partitioning
["aa","b"]could
be produced using 1 cut.
分析:初步分析,根据上题稍加修改,就能计算出来最小分割数,但是一直出现超时的问题。递归耗时太多,超时的代码如下:
Status:
Time Limit Exceeded
class Solution { public: int minCut(string s) { minCutNum = s.length()-1; partitionCore(s,0); return minCutNum; } void partitionCore(string s,int cutNum){ int length = s.length(); if(s.empty()){ -- cutNum; if(cutNum < minCutNum){ minCutNum = cutNum; } return; } if(minCutNum <= cutNum){ return; } for(int i=length; i>=1; --i){ if(isPalindrome(s,0,i-1)){ string leftSubStr = s.substr(i,length-i); partitionCore(leftSubStr,cutNum+1); if(minCutNum == 0){ return; } } } } bool isPalindrome(string s,int i,int j){ while(i <= j){ if(s[i]!=s[j]){ return false; } ++i; --j; } return true; } int minCutNum; };
改进,分析上述超时的原因,有两个方面,第一采用递归而不是循环的方式耗时多,第二在判断字串是否是回文串时,采用遍历操作,很多子问题重复求解。
有了原因的分析,来改进,对于第二个判断字串是否是回文串时,采用动态规划的问题,如判断一个字符串位置i到j的字串是否为回文串,如果i和j相同则只有一个字符,为真;如果s[i]==s[j],则和字符串位置i+1到j-1的分析相同.为了避免多次重复计算,保存各个位置到另外位置的回文串标志。
对于第一个问题,也可以采用动态规划的方法,计算从0位置开始到i位置的分割数,如果0到i字符串就是一个回文串则分割数为0;如果不是,则从0-i开始依次判断其中j到i位置是否是回文串,如果是就是从0位置开始到j位置的分割数+1,得到的最小值为此时要求的分个数。其实思想和上题是一样的。
代码如下:(边界问题处理了好久,一定不要下标越界)
Accepted
class Solution { public: int minCut(string s) { int length = s.length(); if(length <= 1){ return 0; } vector<int> tempMap; for(int i=0; i<length; ++i){ tempMap.push_back(0); } vector<int> minVec; for(int i=0; i<length; ++i){ tempMap[i]= 1; paliMap.push_back(tempMap); tempMap[i] = 0; minVec.push_back(length-1); } for(int i=0; i<length; ++i){ if(isPalindrome(s,0,i)){ minVec[i] = 0; }else{ int tempMin = length-1; for(int j=0; j<i; ++j){ int temp = 0; if(isPalindrome(s,j+1,i)){ temp = minVec[j]+1; }else{ temp = minVec[j] + i - j; } if(temp<tempMin){ tempMin = temp; } } minVec[i] = tempMin; } } return minVec[length-1]; } bool isPalindrome(string& s, int i, int j){ if(i > j || i<0 || j >= s.length()){ return false; } if(paliMap[i][j]){ return true; } if(s[i] == s[j]){ if(i == j-1){ return paliMap[i][j] = 1; }else{ return paliMap[i][j] = paliMap[i+1][j-1]; } }else{ return paliMap[i][j] = 0; } } vector<vector<int>> paliMap; };
相关文章推荐
- leetcode之 Palindrome Partitioning I&II
- [LeetCode] Palindrome Partitioning && Palindrome Partitioning II
- 【LeetCode】palindrome-partitioning i&ii
- 【leetcode】Palindrome Partitioning && Palindrome Partitioning II
- Leetcode 131&132. Palindrome Partitioning I & II
- [Leetcode] #131#132 Palindrome Partitioning I & II
- 【LeetCode】Palindrome Partitioning I && II
- 【LeetCode】Palindrome Partitioning I&II
- leetcode之 Palindrome Partitioning I&II
- LeetCode132 Palindrome Partitioning II&I
- LeetCode Palindrome Partitioning I&&Palindrome Partitioning II
- [LeetCode] Palindrome Partitioning I&II
- Leetcode:Palindrome Partitioning & Palindrome Partitioning II
- LeetCode - Palindrome Partitioning I && II
- leetcode之 Palindrome Partitioning I&II
- Leetcode: palindrome-partitioning && palindrome-partitioning-ii
- Leetcode: Palindrome Partitioning I & II
- leetcode之 Palindrome Partitioning I&II
- LeetCode 20 Palindrome Partitioning II
- [leetcode刷题系列]Palindrome Partitioning II