diff --git a/compareVersionNumber/compareVersionNumber.cpp b/compareVersionNumber/compareVersionNumber.cpp new file mode 100644 index 0000000..60b8e18 --- /dev/null +++ b/compareVersionNumber/compareVersionNumber.cpp @@ -0,0 +1,74 @@ +// Source : https://oj.leetcode.com/problems/compare-version-numbers/ + +/********************************************************************************** + * + * Compare two version numbers version1 and version1. + * If version1 > version2 return 1, if version1 < version2 return -1, otherwise return 0. + * + * You may assume that the version strings are non-empty and contain only digits and the . character. + * The . character does not represent a decimal point and is used to separate number sequences. + * For instance, 2.5 is not "two and a half" or "half way to version three", it is the fifth second-level revision of the second first-level revision. + * + * Here is an example of version numbers ordering: + * 0.1 < 1.1 < 1.2 < 13.37 + * + * Credits:Special thanks to @ts for adding this problem and creating all test cases. + * + **********************************************************************************/ + +class Solution { + public: + vector &split(const string &s, char delim, vector &elems) { + stringstream ss(s); + string item; + while (getline(ss, item, delim)) { + elems.push_back(atoi(item.c_str())); + } + return elems; + } + + + vector split(const string &s, char delim) { + vector elems; + split(s, delim, elems); + return elems; + } + + void rightTrimZero(vector &v){ + while (v.back() == 0){ + v.pop_back(); + } + } + + int compareVersion(string version1, string version2) { + + //split the version by delimer '.' + vector ver1 = split(version1, '.'); + vector ver2 = split(version2, '.'); + + //remove the right Zeros + rightTrimZero(ver1); + rightTrimZero(ver2); + + //compare two versions + for (int i=0; i ver2[i]){ + return 1; + } + } + + //if the above for-loop is not returned, which means they are equal so far + //then check the length. + if (ver1.size() > ver2.size()) { + return 1; + }else if (ver1.size() < ver2.size()) { + return -1; + } + + return 0; + + } + +}; diff --git a/copyListWithRandomPointer/copyListWithRandomPointer.cpp b/copyListWithRandomPointer/copyListWithRandomPointer.cpp new file mode 100644 index 0000000..c0e811e --- /dev/null +++ b/copyListWithRandomPointer/copyListWithRandomPointer.cpp @@ -0,0 +1,186 @@ +// Source : https://oj.leetcode.com/problems/copy-list-with-random-pointer/ + +/********************************************************************************** +* +* A linked list is given such that each node contains an additional random pointer +* which could point to any node in the list or null. +* +* Return a deep copy of the list. +* +* +**********************************************************************************/ + + + +/** + * Definition for singly-linked list with a random pointer. + * struct RandomListNode { + * int label; + * RandomListNode *next, *random; + * RandomListNode(int x) : label(x), next(NULL), random(NULL) {} + * }; + */ + + +/* + * + * The idea as below: + * + * Consider we have a linked list as below: + * + * node1->random = node2; + * node2->random = node1; + * node3->random = node1; + * + * +-------------+ + * | v + * +-------+ +-------+ +-------+ + * | node1 |----> node2 |----> node3 |--->NULL + * +-------+ +-------+ +-------+ + * ^ ^ | | + * | +-----------+ | + * +--------------------------+ + * + * + * To copy the list, + * + * 1) We insert a new node for each node's next position + * + * + * +-------------------------+ + * | v + * +--+----+ +-----+ +-------+ +-----+ +-------+ +-----+ + * | node1 |---> | NEW |----> node2 |---> | NEW |----> node3 |---> | NEW | ---> NULL + * +-------+ +-----+ +---+---+ +-----+ +--+----+ +-----+ + * ^ ^ | | + * | +-----------------------+ | + * +--------------------------------------------------+ + * + * 2) Then, we can construt the new node's random pointer: + * + * (node1->next) -> random = (node1->random) -> next; + * + * 3) After we take out all of the "NEW" node to finish the copy. + * + */ + +class Solution { +public: + RandomListNode *copyRandomList(RandomListNode *head) { + RandomListNode *p = NULL, *h=NULL, *t=NULL; + if (head == NULL){ + return NULL; + } + + //creat a new node for each node and insert its next + p = head; + while ( p != NULL){ + RandomListNode *node = new RandomListNode(p->label); + node->next = p->next; + p->next = node; + p = node->next; + } + + //copy random pointer for each new node + p = head; + while (p != NULL){ + if (p->random != NULL){ + p->next->random = p->random->next; + } + p = p->next->next; + } + + //break to two list + p = head; + h = t = head->next; + while ( p != NULL ){ + p->next = p->next->next; + if (t->next!=NULL){ + t->next = t->next->next; + } + + p = p->next; + t = t->next; + } + + return h; + } +}; + + +/* + * Considering we have a link as below: + * + * + * +-------------+ + * | v + * +-------+ +-------+ +-------+ + * | node1 |----> node2 |----> node3 |--->NULL + * +-------+ +-------+ +-------+ + * ^ ^ | | + * | +-----------+ | + * +--------------------------+ + * + * 1) Using a map to store each node's random pointer's position + * + * map[node1->random] = 1; + * map[node2->random] = 0; + * map[node3->random] = 0; + * + * 2) Clone the linked list (only consider the next pointer) + * + * new1 --> new2 --> new3 --> NULL + * + * 3) Using an array to strore the order of the cloned linked-list + * + * v[0] = &new1 + * v[1] = &new2 + * v[2] = &new3 + * + * 4) Then we can clone the random pointers. + * + * new->random = v [ map[node->random] ] + * + */ +class MySolution { +public: + RandomListNode *copyRandomList(RandomListNode *head) { + + RandomListNode *p = NULL, *h=NULL, *t=NULL; + //using a map to store the random pointer's postion. + map m; + //construct the map + int pos =0; + for ( p = head; p != NULL; p = p->next, pos++){ + m[p] = pos; + } + + //clone the linked list (only consider the next pointer) + //and using a vector to store each node's postion. + vector v; + for (p = head; p != NULL; p = p->next){ + RandomListNode *node = new RandomListNode(p->label); + v.push_back(node); + if (h==NULL){ + h = t = node; + }else{ + t->next = node; + t = node; + } + } + + //p => source link head + //t => new link head + //move the p and t synchronously, and + // t->random = vector[ map[p->random] ]; + for (t=h, p = head; t!=NULL && p!= NULL; p=p->next, t=t->next){ + if (p->random!=NULL) { + pos = m[p->random]; + t->random = v[pos]; + } + } + + return h; + + } +}; diff --git a/distinctSubsequences/distinctSubsequences.cpp b/distinctSubsequences/distinctSubsequences.cpp new file mode 100644 index 0000000..c980158 --- /dev/null +++ b/distinctSubsequences/distinctSubsequences.cpp @@ -0,0 +1,192 @@ +// Source : https://oj.leetcode.com/problems/distinct-subsequences/ + +/***************************************************************************************************** + * + * Given a string S and a string T, count the number of distinct subsequences of S which equals T. + * + * A subsequence of a string is a new string which is formed from the original string by deleting some + * (can be none) of the characters without disturbing the relative positions of the remaining + * characters. (ie, "ACE" is a subsequence of "ABCDE" while "AEC" is not). + * + * Example 1: + * + * Input: S = "rabbbit", T = "rabbit" + * Output: 3 + * Explanation: + * + * As shown below, there are 3 ways you can generate "rabbit" from S. + * (The caret symbol ^ means the chosen letters) + * + * rabbbit + * ^^^^ ^^ + * rabbbit + * ^^ ^^^^ + * rabbbit + * ^^^ ^^^ + * + * Example 2: + * + * Input: S = "babgbag", T = "bag" + * Output: 5 + * Explanation: + * + * As shown below, there are 5 ways you can generate "bag" from S. + * (The caret symbol ^ means the chosen letters) + * + * babgbag + * ^^ ^ + * babgbag + * ^^ ^ + * babgbag + * ^ ^^ + * babgbag + * ^ ^^ + * babgbag + * ^^^ + * + ******************************************************************************************************/ +#include +#include +#include +#include +#include +#include +#include +using namespace std; + +//===================== +// Dynamic Programming +//===================== +// +// The idea as below: +// +// Considering m[i][j] means the distance from T[i] to S[j], and add the empty "" case, then, +// +// A) Initialization for empty case: m[0][j] = 1; +// +// B) Calculation +// +// a) Target-len > Source-len cannot found any substring +// i > j : m[i][j] = 0; +// +// b) if not equal, take the value of T[i] => S[j-1] (e.g. ["ra" => "rabb"] =["ra" => "rab"] ) +// S[j] != T[i] : m[i][j] = m[i][j-1] +// +// c) if equal. (e.g. ["rab" => "rabb"] = ["rab" =>"rab"] + ["ra" => "rab"] ) +// S[j] == T[i] : m[i][j] = m[i][j-1] + m[i-1][j-1] +// +// 1) Initialize a table as below +// "" r a b b b i t +// "" 1 1 1 1 1 1 1 1 +// r +// b +// t +// +// 2) Calculation +// "" r a b b b i t +// "" 1 1 1 1 1 1 1 1 +// r 0 1 1 1 1 1 1 1 +// b 0 0 0 1 2 3 3 3 +// t 0 0 0 0 0 0 0 3 +// +int numDistinct1(string S, string T) { + vector< vector > m(T.size()+1, vector(S.size()+1)); + + for (int i=0; ij ) { + m[i][j] = 0; + continue; + } + if (S[j-1] == T[i-1]){ + m[i][j] = m[i][j-1] + m[i-1][j-1]; + } else { + m[i][j] = m[i][j-1] ; + } + } + } + return m[T.size()][S.size()]; +} + + +//===================== +// Dynamic Programming +//===================== +// +// The idea here is an optimization of above idea +// (It might be difficult to understand if you don't understand the above idea) +// +// For example: +// +// S = "abbbc" T="abb" +// posMap = { [a]={0}, [b]={2,1} } <- the map of T's every char. +// numOfSubSeq = {1, 0, 0, 0 } +// +// S[0] is 'a', pos is 0, numOfSubSeq = {1, 0+1, 0, 0}; +// +// S[1] is 'b', pos is 2, numOfSubSeq = {1, 1, 0, 0+0}; +// pos is 1, numOfSubSeq = {1, 1, 0+1, 0}; +// +// S[2] is 'b', pos is 2, numOfSubSeq = {1, 1, 1, 0+1}; +// pos is 1, numOfSubSeq = {1, 1, 1+1, 1}; +// +// S[3] is 'b', pos is 2, numOfSubSeq = {1, 1, 2, 2+1}; +// pos is 1, numOfSubSeq = {1, 1, 1+2, 3}; +// +// S[4] is 'c', not found, numOfSubSeq = {1, 1, 3, 3}; +// +// +int numDistinct2(string S, string T) { + + map< char, vector > pos_map; + int len = T.size(); + vector numOfSubSeq(len+1); + numOfSubSeq[0] = 1; + + for (int i=len-1; i>=0; i--){ + pos_map[T[i]].push_back(i); + } + + for (int i=0; i2){ + s = argv[1]; + t = argv[2]; + } + cout << "S=\"" << s << "\" T=\"" << t << "\"" << endl; + cout << "numDistinct = " << numDistinct(s, t) << endl; + return 0; +} diff --git a/house Robber 2/houserobberii.cpp b/house Robber 2/houserobberii.cpp new file mode 100644 index 0000000..36dbf8f --- /dev/null +++ b/house Robber 2/houserobberii.cpp @@ -0,0 +1,55 @@ +// Source : https://leetcode.com/problems/house-robber-ii/ + +/********************************************************************************** + * + * Note: This is an extension of House Robber. + * + * After robbing those houses on that street, the thief has found himself a new place + * for his thievery so that he will not get too much attention. This time, all houses + * at this place are arranged in a circle. That means the first house is the neighbor + * of the last one. Meanwhile, the security system for these houses remain the same as + * for those in the previous street. + * + * Given a list of non-negative integers representing the amount of money of each house, + * determine the maximum amount of money you can rob tonight without alerting the police. + * + * Credits:Special thanks to @Freezen for adding this problem and creating all test cases. + * + **********************************************************************************/ + + +class Solution { +public: + int orginal_rob(vector &money, int start, int end) { + int n2=0; + int n1=0; + + for (int i=start; i& nums) { + int n = nums.size(); + switch (n) { + case 0: + return 0; + case 1: + return nums[0]; + case 2: + return max(nums[0], nums[1]); + default: + /* + * the idea is we cannot rob[0] and rob[n-1] at same time + * so, we rob [0 .. n-2] or [1 .. n-1], can return the maxinum one. + */ + int m1 = orginal_rob(nums, 0, n-1); + int m2 = orginal_rob(nums, 1, n); + + return max(m1, m2); + } + } +}; diff --git a/houserobber/houserobber.cpp b/houserobber/houserobber.cpp new file mode 100644 index 0000000..8ce098c --- /dev/null +++ b/houserobber/houserobber.cpp @@ -0,0 +1,98 @@ +// Source : https://leetcode.com/problems/house-robber/ + + +/********************************************************************************** + * + * You are a professional robber planning to rob houses along a street. Each house has + * a certain amount of money stashed, the only constraint stopping you from robbing + * each of them is that adjacent houses have security system connected and it will + * automatically contact the police if two adjacent houses were broken into on the same night. + * + * Given a list of non-negative integers representing the amount of money of each house, + * determine the maximum amount of money you can rob tonight without alerting the police. + * + * + **********************************************************************************/ + +#include +#include +#include +#include +using namespace std; +/* + * Dynamic Programming + * + * We can easy find the recurive fomular: + * + * dp[n] = max( + * dp[n-1], // the previous house has been robbed. + * dp[n-2] + money[n] // the previous house has NOT been robbed. + * ) + * + * The initalization is obvious: + * dp[1] = money[1] + * dp[2] = max(money[1], money[2]) + * + */ +int rob1(vector &money) { + + int n = money.size(); + if (n==0) return 0; + + vector dp(n, 0); + if (n>=1) dp[0] = money[0]; + if (n>=2) dp[1] = max(money[0], money[1]); + + for (int i=2; i &money) { + int n2=0; // dp[i-2]; + int n1=0; // dp[i-1]; + + for (int i=0; i &num) { + if (rand()%2) + return rob1(num); + return rob2(num); +} + +void printVector( vector &v ){ + cout << '[' ; + for(int i=0; i money; + if (argc>1){ + for (int i=1; i