1.clone_graphnode
1 /** 2 * Definition for undirected graph. 3 * struct UndirectedGraphNode { 4 * int label; 5 * vector<UndirectedGraphNode *> neighbors; 6 * UndirectedGraphNode(int x) : label(x) {}; 7 * }; 8 */ 9 class Solution { 10 public: 11 UndirectedGraphNode *clone(UndirectedGraphNode *node, map<int,UndirectedGraphNode*> &table) 12 { 13 if(node==NULL) 14 return NULL; 15 16 if(table.find(node->label)!=table.end()) 17 return table[node->label]; 18 19 UndirectedGraphNode *newnode=new UndirectedGraphNode(node->label); 20 table[newnode->label]=newnode; 21 22 for(int i=0;i<node->neighbors.size();i++) 23 { 24 UndirectedGraphNode *neighbor=clone(node->neighbors[i],table); 25 newnode->neighbors.push_back(neighbor); 26 } 27 28 return newnode; 29 } 30 /** 31 * @param node: A undirected graph node 32 * @return: A undirected graph node 33 */ 34 UndirectedGraphNode *cloneGraph(UndirectedGraphNode *node) { 35 map<int,UndirectedGraphNode*> visitTable; 36 return clone(node,visitTable); 37 } 38 };
2.Palindrome Partitioningios
理解 substr函数的用法c++
1 #include<string> 2 #include<iostream> 3 using namespace std; 4 main() 5 { 6 string s("12345asdf"); 7 string a=s.substr(0,5); //得到字符串s中 从第0位开始的长度为5的字符串//默认时的长度为从开始位置到尾 8 string b = s.substr(4); //得到字符串从第4位开始的字符串 9 cout<<a<<endl; 10 } 11 输出结果为: 12 12345 13 5asdf
Palindrome Partitioning 源码:git
1 Given a string s, partition s such that every substring of the partition is a palindrome. 2 Return all possible palindrome partitioning of s. 3 For example, given s ="aab", 4 Return 5 6 [ 7 ["aa","b"], 8 ["a","a","b"] 9 ] 10 11 12 13 class Solution { 14 public: 15 //path保存每种方案,res全部方案 16 void dfs(string s,vector&path,vector>&res){ 17 18 //查到最后,将该方案添加,返回 19 if(s.size() < 1) 20 { 21 res.push_back(path); 22 return; 23 } 24 25 //从当前串的头开始,检查回文串 26 for(int i = 0;i<s.size(),i++) 27 { 28 int begin = 0; 29 int end = i; 30 while(begin < end){ 31 if(s[begin] == s[end]){ 32 begin++; 33 end--; 34 } 35 else 36 break; 37 } 38 if(begin >= end) 39 {//找到回文串 40 path.push_back(s.substr(0,i+1));//添加到path中 41 dfs(s.substr(i+1), path,res);//递归向后查 42 path.pop_back();//回溯,检查多种不一样方案 43 } 44 } 45 46 47 } 48 49 //判断一个字符串是否为回文串 50 vector> partition(string s) { 51 vector>res; 52 vectorpath; 53 dfs(s,path,res); 54 return res; 55 } 56 };
3.valid-palindrome算法
在此介绍两个函数:数组
isalnum(char c) 用法:#include <ctype.h> 功能:判断字符变量c是否为字母或数字 说明:当c为数字0-9或字母a-z及A-Z时,返回非零值,不然返回零。 tolower(int c) 功 能: 把 字符转换成小写字母,非字母字符不作出处理 头文件:在VC6.0能够是 ctype.h或者 stdlib.h,经常使用ctype.h
valid-palindrome源码app
bool isPalindrome(string s) { int i = 0; int len = s.size(); int j = len-1; while(i<j) { while(i<j&&!isalnum(s[i])) i++; while(i<j&&!isalnum(s[j])) j--; if(i<j && tolower(s[i])!=tolower(s[j])) { return false; } i++;j--; } return true; }
4.single-numberide
Given an array of integers, every element appears twice except for one. Find that single one. Note: Your algorithm should have a linear runtime complexity. Could you implement it without using extra memory? //思路:两个相同的数异或为0 //例子:1^2^3^4^4^3^2 = 2^2^3^3^4^4^1 = 1 public class Solution { public int singleNumber(int[] A) { int result = A[0]; for(int i=1; i<A.length; i++){ result = result ^ A[i]; } return result; } }
5.single-number-ii函数
/* Given an array of integers, every element appears three times except for one. Find that single one. Note: Your algorithm should have a linear runtime complexity. Could you implement it without using extra memory? */ int singleNumberII(int A[], int n) { int ans = 0; for (int i = 0; i < 32; i++) { int c = 0, d = 1<<i; for (int j = 0; j < n; j++) if (A[j] & d) c++; //对每一位进行判断,若是数组中的全部数字通过判断后发现结果不是3的倍数 说明出现次数不为3的那个数的 二进制为1.因此要或运算。这样ans为最后的结果 if (c%3) ans |= d; } return ans; }
6.two-sumthis
这里用到了C++中的哈希容器unordered_map vector<int> twoSum(vector<int>& nums, int target) { vector<int> res; int len = nums.size(); unordered_map<int, int> m; for (int i = 0; i < len; i++){ if (m.count(target - nums[i])){ res.push_back(m[target - nums[i]]+1); res.push_back(i+1); return res; } m[nums[i]] = i; } return res; } 补充知识: unordered_map::count 查找与指定键匹配的元素数。 size_type count(const Key& keyval) const; 参数 keyval 要搜索的键值。 备注 成员函数返回由分隔的范围中的元素数目
7. add-two-numbers
/* You are given two linked lists representing two non-negative numbers. The digits are stored in reverse order and each of their nodes contain a single digit. Add the two numbers and return it as a linked list. Input: (2 -> 4 -> 3) + (5 -> 6 -> 4) Output: 7 -> 0 -> 8 */ struct ListNode { int val; ListNode *next; ListNode(int x) : val(x), next(NULL) {} }; /* 最直白的想法就是将两个字符串翻转, 而后相加,获得的结果再发转 如今的解法,直接从左到右相加,而后向右进位 */ class Solution { public: ListNode *addTwoNumbers(ListNode *l1, ListNode *l2) { ListNode* ptr = new ListNode(0); ListNode* head = ptr; int tmp_carry = 0; int sum; while( l1 || l2 ) { sum = 0; if( l1 ) { sum += l1->val; l1 = l1->next; } if( l2 ) { sum += l2->val; l2 = l2->next; } ptr->next = new ListNode( (sum + tmp_carry)%10 ); ptr = ptr->next; tmp_carry = (sum + tmp_carry)/10; } if( tmp_carry ) { ptr->next = new ListNode( tmp_carry ); } return head->next; } }; 结果返回的是一个带头结点的链表,在链表的生成过程当中,须要一个一个的产生节点来生成,每次生成链表中的一个节点。
8. longest-substring-without-repeating-characters
/* Given a string, find the length of the longest substring without repeating characters. For example, the longest substring without repeating letters for "abcabcbb" is "abc", which the length is 3. For "bbbbb" the longest substring is "b", with the length of 1 题意在原串中找到最长的每一个字母最多出现一次的字符串 */ int lengthOfLongestSubstring(string s) { int i,j,len=0,maxx=0; bool sign[30]; memset(sign,0,sizeof(sign)); for(i=0,j=0;j<s.length();++j) { while(sign[s[j]-'a']==1) { sign[s[i]-'a']=0; ++i; } sign[s[j]-'a']=1; maxx=max(maxx,j-i+1); } return maxx; } //理解:在while循环中,虽然j没有改变,可是i的变化也会使得循环条件的变化
9. longest-palindromic-substring
/* Given a string S, find the longest palindromic substring in S. You may assume that the maximum length of S is 1000, and there exists one unique longest palindromic substring. */ /* 解析: 使用动态规划的话,首先咱们须要知道解法中得递推关系。好比字符串“ababa”,若是咱们已经知道“bab”是回文,那么显然“ababa”也是回文,由于首字符和尾字符是相等的。 定义dp[i][j]:若是子串Si到Sj是一个回文串,那么该项为true,不然为false 咱们知道有这样的递推关系以下: dp[i][j]为true 成立的条件是 dp[i+1][j-1] 为真而且Si==Sj 基础条件是: dp[i][i]=true 表明一个字符是一个回文串 dp[i][i+1]=true 表明相邻字符是回文串 那么在基础条件下 仅仅计算字符串长度分别为 3 4 一直到s.size() 是不是回文串便可,固然每次计算的时候 记录最长回文串的索引和回文串长度 */ string longestPalindrome(string s) { int i = 0; int j = 0; int len = s.size(); int k = 0; vector<vector<bool> > a(len,vector<bool>(len,false)); // bool a[1000][1000]={false}; int maxsize = 1; int maxindex = 0; for(i = 0;i<len;i++) { a[i][i]=true; } for(i=0;i<len-1;i++) { if(s[i]==s[i+1]) { a[i][i+1]=true; maxindex = i; maxsize = 2; } } for(k = 3;k<=len;k++) { for(i =0;i<len-k+1;i++) { j = i+k-1; if(s[i]==s[j]&&a[i+1][j-1]) { a[i][j]=true; maxindex = i; maxsize = k; } } } return s.substr(maxindex,maxsize); }
10. maximum-subarray
/* Find the contiguous subarray within an array (containing at least one number) which has the largest sum. For example, given the array[−2,1,−3,4,−1,2,1,−5,4], the contiguous subarray[4,−1,2,1]has the largest sum =6. click to show more practice. More practice: If you have figured out the O(n) solution, try coding another solution using the divide and conquer approach, which is more subtle. */ /* 解析: 典型的动态规划问题: 定义子问题:dp[i]为以第i个元素结尾的最大连续子数组和 而后在循环记录最大连续子数组和的同时记录 最大连续子数组和的值 等待循环完毕之时,即函数返回之时。 */ int maxSubArray(int A[], int n) { int i = 0; vector<int> sum(n,0); int maxr; sum[0]=A[0]; maxr = sum[0]; for(i = 1;i<n;i++) { sum[i]=max(A[i],sum[i-1]+A[i]); maxr = max(sum[i],maxr); } return maxr; }
11. unique-paths
/* A robot is located at the top-left corner of a m x n grid The robot can only move either down or right at any point in time. The robot is trying to reach the bottom-right corner of the grid How many possible unique paths are there? */ /* dp[i][j] 表明走到i行j列 的路径数 解析:从题目咱们能够知道 dp[m][n]=dp[m-1][n]+dp[m][n-1] 基础条件:dp矩阵的第一行和第一列的值为1。意思就是说到达第一行和第一列的路径数为1. 这样就能够动态规划的求解除了第一行和第一列以外的 空格的路径数,不断的循环求解便可求得后下角空格的路径数 */ int uniquePaths(int m, int n) { vector<vector<int> > dp(m,vector<int>(n,0)); int i = 0; int j = 0; for(i=0;i<m;i++) { dp[i][0]=1; } for(i =0;i<n;i++) { dp[0][i]=1; } for(i = 1;i<m;i++) { for(j =1;j<n;j++) { dp[i][j]=dp[i-1][j]+dp[i][j-1]; } } return dp[m-1][n-1]; }
12. unique-paths-ii
/* Follow up for "Unique Paths": Now consider if some obstacles are added to the grids. How many unique paths would there be? An obstacle and empty space is marked as1and0respectively in the grid. For example, There is one obstacle in the middle of a 3x3 grid as illustrated below. [ [0,0,0], [0,1,0], [0,0,0] ] The total number of unique paths is2. Note: m and n will be at most 100. */ /* 解析: 动态规划 这个问题和前一个问题相比较,变化的就是加了障碍物,也就是说基础条件须要发生变化 第一行和第一列不在初始化为1 ,其值要看是否有障碍物 若是有障碍物 将其值赋值为0,若是没有障碍物 其值为前一个的dp值。对于第1行和第一列以后的值 若是有障碍物 赋值为0 ,没有障碍物,其值为左边dp值+上边dp值。 前提条件:dp[0][0]= obstacleGrid[0][0]==1?0:1 第一行和第一列是在第一个空格已知的前提下求解的 第一行和第一列以后的行数和列数是在 第一行和第一列的前提下求解的 */ int uniquePathsWithObstacles(vector<vector<int> > &obstacleGrid) { int i = 0; int j = 0; int m = obstacleGrid.size(); int n = obstacleGrid[0].size(); vector<vector<int> > dp(m,vector<int>(n,0)); dp[0][0]=obstacleGrid[0][0]==1?0:1; for(i = 1;i<m;i++) { dp[i][0]=obstacleGrid[i][0]==1?0:dp[i-1][0]; } for(i = 1;i<n;i++) { dp[0][i]=obstacleGrid[0][i]==1?0:dp[0][i-1]; } for(i = 1;i<m;i++) { for(j=1;j<n;j++) { if(obstacleGrid[i][j]==0) { dp[i][j] = dp[i-1][j]+dp[i][j-1]; } else { dp[i][j]=0; } } } return dp[m-1][n-1]; }
13. minimum-path-sum
/* Given a m x n grid filled with non-negative numbers, find a path from top left to bottom right which minimizes the sum of all numbers along its path. Note: You can only move either down or right at any point in time. Subscribe to see which companies asked this question Hide Tags Array Dynamic Programming Show Similar Problems */ /* 解析: dp[0][0]=grid[0][0] 第一行的路径是左边的路径和当前位置的值相加的结果 第一列的路径是上边的路径和当前位置的值相机的结果 剩下点的路劲和都是来自二维数组上一行的最小路劲和或者来自左一列的最小路劲和与当前位置的值相加的结果 显然有:dp[m,n]=min(dp[m-1,n]+grid[m,n],dp[m,n-1]+grid[m,n]) */ int minPathSum(vector<vector<int> > &grid) { int i = 0; int j = 0; int m = grid.size(); int n = grid[0].size(); vector<vector<int> > dp(m,vector<int> (n,0)); dp[0][0]=grid[0][0]; for(i = 1;i<m;i++) { dp[i][0]=dp[i-1][0]+grid[i][0]; } for(i = 1;i<n;i++) { dp[0][i]=dp[0][i-1]+grid[0][i]; } for(i =1;i<m;i++) { for(j=1;j<n;j++) { dp[i][j]=min(dp[i-1][j]+grid[i][j],dp[i][j-1]+grid[i][j]); } } return dp[m-1][n-1]; }
14. climbing-stairs
/* ou are climbing a stair case. It takes n steps to reach to the top. Each time you can either climb 1 or 2 steps. In how many distinct ways can you climb to the top? */ /* 解析: 动态规划 由题可知,dp[0]=1 dp[1]=2 爬到第三层楼的方法为使用climb1 step的方法+使用climb 2steps的方法 即dp[3]=dp[3-1]+dp[3-2] 综上:dp[i]=dp[i-1]+dp[i-2]; */ int climbStairs(int n) { vector<int> dp(n,0); dp[0]=1; dp[1]=2; int i = 0; for(i = 2;i<n;i++) { dp[i]=dp[i-1]+dp[i-2]; } return dp[n-1]; }
15. unique-binary-search-trees
/* Given n, how many structurally unique BST's (binary search trees) that store values 1...n? For example, Given n = 3, there are a total of 5 unique BST's. */ /* 解析: 动态规划问题,因此必须努力去找到和之前的子问题的联系。 断言:由1,2,3,...,n构建的二叉查找树,以i为根节点,左子树由[1,i-1]构成,其右子树由[i+1,n]构成。 定义子问题:定义dp[i]为以1-i 能产生的二叉搜索树的数目 若数组为空,则只有一种BST,即空树,dp[0]=1; 若数组仅有一个元素1,单个节点,dp[1]=1; 若数组有两个元素1,2,则有两种可能,dp[2]=2; 若数组有三个元素1,2,3,则有5中状况,题目已经说了, n=4呢?显示此问题玄机的时候到了:寻找与上面已推出子问题的关系: 若是1为根,则左子树0个元素因此1种状况,右子树3个元素(2,3,4),显然为5种状况 若是2为根,则左子树1个元素因此1种状况,右子树2个元素(3,4),显然为2 若是3为根,则左子树2个元素因此2种状况,右子树1个元素(4),显然为2 若是4为根,则左子树3个元素因此5种状况,右子树3个元素(无)为一种状况,显然为5 也就是说 n=4 也就是说要考虑4种状况(可用循环,循环里面就是子问题了) 因此先把子问题就出来 而后在循环的求大问题 */ int numTrees(int n) { vector<int> dp(n+1,0); dp[0]=1; dp[1]=1; int i = 0; int j = 0; for(i=2;i<=n;i++) { for(j=1;j<=i;j++) { dp[i] += dp[j-1]*dp[i-j]; } } return dp[n]; }
16.best-time-to-buy-and-sell-stock
/* Say you have an array for which the i th 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. */ /* 解析: 初始条件就是dp[0]=prices[0] 而后在维护一个最大差值变量maxz dp[i]表明找这个数组里面的最小值 同时在求得最小值的时候记录maxz */ int maxProfit(vector<int> &prices) { int n = prices.size(); if(n==0) { return 0; } vector<int> dp(n,0); int i = 0; int maxz = 0; dp[0]=prices[0]; for(i=1;i<n;i++) { dp[i]=min(dp[i-1],prices[i]); maxz = max(maxz,prices[i]-dp[i]); } return maxz; }
17. 风口的猪-中国牛市
/* 风口之下,猪都能飞。当今中国股市牛市,真可谓“错过等七年”。 给你一个回顾历史的机会,已知一支股票连续n天的价格走势,以长度为n的整数数组表示,数组中第i个元素(prices[i])表明该股票第i天的股价。 假设你一开始没有股票,但有至多两次买入1股然后卖出1股的机会,而且买入前必定要先保证手上没有股票。若两次交易机会都放弃,收益为0。 设计算法,计算你能得到的最大收益。 输入数值范围:2<=n<=100,0<=prices[i]<=100 示例1 输入 3,8,5,1,7,8 输出 12 */ /* 解析: 思路和前一个题的思路类似,可是不一样的是 从左往右是找dp[i]最小的,从右往左是找dp[i]最大的,为了不跨界变量 (买入前必定要先保证手上没有股票),循环的找利益最大的。 */