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]最大的,爲了不跨界變量 (買入前必定要先保證手上沒有股票),循環的找利益最大的。 */