Leetcode模拟题篇
高精度非负整数的乘法。
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 string multiply(string num1, string num2) { 2 string sum(num1.size() + num2.size(), '0'); 3 4 for (int i = num1.size() - 1; 0 <= i; --i) { 5 int carry = 0; 6 for (int j = num2.size() - 1; 0 <= j; --j) { 7 int tmp = (sum[i + j + 1] - '0') + (num1[i] - '0') * (num2[j] - '0') + carry; 8 sum[i + j + 1] = tmp % 10 + '0'; 9 carry = tmp / 10; 10 } 11 sum[i] += carry; 12 } 13 14 size_t startpos = sum.find_first_not_of("0"); 15 if (string::npos != startpos) { 16 return sum.substr(startpos); 17 } 18 return "0"; 19 }
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 string multiply(string num1, string num2) { 2 int i, j; 3 int m = num1.size(), n = num2.size(); 4 // max (m + n) digits 5 vector<int> product(m + n, 0); 6 string result; 7 8 // reverse for ease of calc 9 reverse(num1.begin(), num1.end()); 10 reverse(num2.begin(), num2.end()); 11 12 // digit i * digit j contributes to digit i + j 13 for (i = 0; i < m; i++) { 14 for (j = 0; j < n; j++) { 15 product[i + j] += (num1[i] - '0') * (num2[j] - '0'); 16 product[i + j + 1] += product[i + j] / 10; 17 product[i + j] %= 10; 18 } 19 } 20 21 // remove leading 0; keep last 0 if all 0 22 for (i = m + n - 1; i > 0 && 0 == product[i]; i--); 23 24 for (; i >= 0; i--) 25 result += to_string(product[i]); 26 27 return result; 28 }
包含()+-、空格的非负整数的表达式求值。
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 int calculate(string s) { 2 stack <int> nums, ops; 3 int num = 0; 4 int rst = 0; 5 int sign = 1; 6 for (char c : s) { 7 if (isdigit(c)) { 8 num = num * 10 + c - '0'; 9 } 10 else { 11 rst += sign * num; 12 num = 0; 13 if (c == '+') sign = 1; 14 if (c == '-') sign = -1; 15 if (c == '(') { 16 nums.push(rst); 17 ops.push(sign); 18 rst = 0; 19 sign = 1; 20 } 21 if (c == ')' && ops.size()) { 22 rst = ops.top() * rst + nums.top(); 23 ops.pop(); nums.pop(); 24 } 25 } 26 } 27 rst += sign * num; 28 return rst; 29 }
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 class Solution { 2 public: 3 int calculate(string s) { 4 int n = s.size(); 5 stack<int> s1; 6 stack<char> s2; 7 string v; 8 for(int i = n - 1; i >= 0; i--){ 9 if(s[i] == ')' || s[i] == '+' || s[i] == '-') s2.push(s[i]); 10 else if(s[i] >= '0' && s[i] <= '9'){ 11 v = s[i] + v; 12 if(i == 0 || s[i - 1] < '0' || s[i - 1] > '9'){ 13 s1.push(stoi(v)); 14 v = ""; 15 } 16 } else if(s[i] == '('){ 17 while(s2.top() != ')') cal(s1, s2); 18 s2.pop(); 19 } 20 } 21 while(!s2.empty()) cal(s1, s2); 22 return s1.top(); 23 } 24 25 void cal(stack<int> &s1, stack<char> &s2){ 26 int v1 = s1.top(); s1.pop(); 27 int v2 = s1.top(); s1.pop(); 28 char c = s2.top(); s2.pop(); 29 if(c == '+') s1.push(v1 + v2); 30 if(c == '-') s1.push(v1 - v2); 31 } 32 };
包含+-*/、空格的非负整数的表达式求值。
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 int calculate(string s) { 2 stack<char> opS; 3 stack<int> numS; 4 s.push_back(')'); // to make sure the last operand will be saved in the stack e.g. 1+2*3), 2*3 will be calculated and push in the stack 5 opS.push('+'); // sign for the first operand 6 7 int i, curNum, len = s.size(), res =0; 8 for(i=0,curNum=0; i<len; ++i) 9 { 10 if(isdigit(s[i])) curNum = curNum*10 + s[i] -'0'; // digit, recover the oprand 11 else if(isspace(s[i])) continue; // skip the space 12 else 13 { 14 switch(opS.top()) 15 { 16 case '*': // if the last operator is * / , do calculation 17 case '/': 18 curNum = opS.top()=='/'?numS.top()/curNum : numS.top()*curNum; 19 opS.pop(); 20 numS.pop(); 21 } 22 numS.push(curNum); / 23 curNum = 0; 24 opS.push(s[i]); 25 } 26 } 27 opS.pop(); // skip the ")" 28 while(!opS.empty()) {res += (opS.top()=='-')? -numS.top(): numS.top(); opS.pop(); numS.pop();} 29 return res; 30 }
附含括号的代码:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 int calculate(string s) { 2 stack<char> opS; 3 stack<int> numS; 4 s = '(' + s + ')'; 5 6 int i, curNum = 0, len = s.size(); 7 for(i=0; i<len; ++i) 8 { 9 if(isdigit(s[i])) curNum = curNum*10 + s[i] -'0'; 10 else if(isspace(s[i])) continue; 11 else if(s[i] == '(') 12 { 13 opS.push('('); 14 opS.push('+'); 15 } 16 else 17 { 18 switch(opS.top()) 19 { 20 case '*': 21 case '/': 22 curNum = opS.top()=='/'?numS.top()/curNum : numS.top()*curNum; 23 opS.pop(); 24 numS.pop(); 25 } 26 switch(s[i]) 27 { 28 case ')': 29 if('-'== opS.top()) curNum = -curNum; 30 opS.pop(); 31 32 while(opS.top()!='(') 33 { 34 curNum += (opS.top()=='-')? -numS.top(): numS.top(); 35 opS.pop(); 36 numS.pop(); 37 } 38 opS.pop(); // skip '(' 39 break; 40 default: //+,-,*,/ 41 opS.push(s[i]); 42 numS.push(curNum); 43 curNum = 0; 44 } 45 } 46 } 47 return curNum; 48 }
中缀表达式转逆波兰式
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 class Solution { 2 public: 3 /** 4 * @param expression: A string array 5 * @return: The Reverse Polish notation of this expression 6 */ 7 vector<string> convertToRPN(vector<string> &expression) { 8 // write your code here 9 vector<string>op;//符号栈 10 vector<string>num;//表达式结果栈 11 for(int i=0;i<expression.size();i++)//一遍扫描 12 { 13 if(expression[i]=="+" || expression[i]=="-")//处理加号、减号 14 { 15 if(op.size()==0) 16 op.push_back(expression[i]); 17 else 18 { 19 while(op.size()!=0 && (op[op.size()-1]=="*" || op[op.size()-1]=="/" ||op[op.size()-1]=="+" || op[op.size()-1]=="-")) 20 { 21 string s=op.back(); 22 op.pop_back(); 23 num.push_back(s); 24 25 } op.push_back(expression[i]); 26 } 27 if(op[op.size()-1]=="(") 28 { 29 op.push_back(expression[i]); 30 } 31 } 32 else if(expression[i]=="*" || expression[i]=="/")//处理乘号、除号 33 { 34 if(op.size()==0) 35 op.push_back(expression[i]); 36 else if(op[op.size()-1]=="*" || op[op.size()-1]=="/" ) 37 { 38 string s=op.back(); 39 op.pop_back(); 40 num.push_back(s); 41 op.push_back(expression[i]); 42 } 43 else if(op[op.size()-1]=="+" || op[op.size()-1]=="-") 44 { 45 op.push_back(expression[i]); 46 } 47 else if(op[op.size()-1]=="(") 48 { 49 op.push_back(expression[i]); 50 } 51 } 52 else if(expression[i]=="(")//处理左括号 53 { 54 op.push_back(expression[i]); 55 } 56 else if(expression[i]==")")//处理右括号 57 { 58 while(op.back()!="(") 59 { 60 string s=op.back(); 61 op.pop_back(); 62 num.push_back(s); 63 } 64 op.pop_back(); 65 } 66 else//运算数直接压入表达式结果栈 67 { 68 num.push_back(expression[i]); 69 } 70 } 71 while(op.size()!=0)//符号栈仍有符号时,将其压入表达式结果栈 72 { 73 string s=op.back(); 74 op.pop_back(); 75 num.push_back(s); 76 } 77 return num; 78 } 79 };
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 int symbol_priority(char &c) 2 { 3 if (c == '(')return 0; 4 else if (c == '+' || c == '-')return 1; 5 else if (c == '*' || c == '/')return 2; 6 else if (c == ')')return 3; 7 else return -1; 8 } 9 //判断优先级 10 bool is_high(char &c) 11 { 12 if (symbol.empty())return true; 13 else if (c == '(')return true; 14 else if (symbol_priority(symbol.top())<symbol_priority(c))return true; 15 else return false; 16 } 17 double calculator::operation(double & a, char c, double b) 18 { 19 if (c == '+')a += b; 20 else if (c == '-')a -= b; 21 else if (c == '*')a *= b; 22 else if (c == '/') 23 { 24 if (abs(b) <= eps)return false; 25 else return a /= b; 26 } 27 else return false; 28 return true; 29 } 30 //中缀转后缀 31 void calculator::do_suffix() 32 { 33 while (!expression.empty()) 34 { 35 std::string str = expression.front(); 36 expression.pop(); 37 if (is_symbol(str[0])) 38 { 39 if (is_high(str[0])) 40 { 41 if (str[0] == ')') 42 { 43 while (symbol.top() != '(') 44 { 45 std::string temp = ""; 46 suffix.push(temp+=symbol.top()); 47 symbol.pop(); 48 } 49 symbol.pop(); 50 } 51 else 52 symbol.push(str[0]); 53 } 54 else 55 { 56 while (!symbol.empty()) 57 { 58 if (is_high(str[0])) 59 { 60 break; 61 } 62 std::string temp = ""; 63 suffix.push(temp+=symbol.top()); 64 symbol.pop(); 65 } 66 symbol.push(str[0]); 67 } 68 } 69 else 70 { 71 suffix.push(str); 72 } 73 } 74 while (!symbol.empty()) 75 { 76 std::string temp = ""; 77 suffix.push(temp += symbol.top()); 78 symbol.pop(); 79 } 80 } 81 //计算 82 bool calculator::count() 83 { 84 std::stack<double>number; 85 while (!suffix.empty()) 86 { 87 std::string temp = suffix.front(); 88 suffix.pop(); 89 if (!is_symbol(temp[0])) 90 { 91 number.push(atof(temp.c_str())); 92 } 93 else 94 { 95 double temp1 = number.top(); number.pop(); 96 double temp2 = number.top(); number.pop(); 97 if (!operation(temp2,temp[0],temp1)) 98 { 99 return false; 100 } 101 else 102 { 103 number.push(temp2); 104 } 105 } 106 } 107 answer = number.top(); 108 number.pop(); 109 return true; 110 }
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 class LRUCache { 2 public: 3 list<pair<int, int>> storage; 4 unordered_map<int, list<pair<int, int>>::iterator> mapping; 5 int capacity; 6 7 LRUCache(int capacity) : capacity(capacity) { 8 9 } 10 11 int get(int key) { 12 if (mapping.find(key) == mapping.end()) 13 return -1; 14 int val = mapping[key]->second; 15 storage.erase(mapping[key]); 16 storage.push_back({key, val}); 17 mapping[key] = --storage.end(); 18 return val; 19 } 20 21 void put(int key, int value) { 22 if (get(key) == -1) { 23 if (storage.size() == capacity) { 24 mapping.erase(storage.begin()->first); 25 storage.erase(storage.begin()); 26 } 27 storage.push_back({key, value}); 28 mapping[key] = --storage.end(); 29 } else { 30 list<pair<int, int>>::iterator node = storage.end(); 31 node--; 32 node->second = value; 33 } 34 } 35 }; 36 37 /** 38 * Your LRUCache object will be instantiated and called as such: 39 * LRUCache obj = new LRUCache(capacity); 40 * int param_1 = obj.get(key); 41 * obj.put(key,value); 42 */
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 class LFUCache { 2 int cap; 3 int size; 4 int minFreq; 5 unordered_map<int, pair<int, int>> m; //key to {value,freq}; 6 unordered_map<int, list<int>::iterator> mIter; //key to list iterator; 7 unordered_map<int, list<int>> fm; //freq to key list; 8 public: 9 LFUCache(int capacity) { 10 cap=capacity; 11 size=0; 12 } 13 14 int get(int key) { 15 if(m.count(key)==0) return -1; 16 17 fm[m[key].second].erase(mIter[key]); 18 m[key].second++; 19 fm[m[key].second].push_back(key); 20 mIter[key]=--fm[m[key].second].end(); 21 22 if(fm[minFreq].size()==0 ) 23 minFreq++; 24 25 return m[key].first; 26 } 27 28 void set(int key, int value) { 29 if(cap<=0) return; 30 31 int storedValue=get(key); 32 if(storedValue!=-1) 33 { 34 m[key].first=value; 35 return; 36 } 37 38 if(size>=cap ) 39 { 40 m.erase( fm[minFreq].front() ); 41 mIter.erase( fm[minFreq].front() ); 42 fm[minFreq].pop_front(); 43 size--; 44 } 45 46 m[key]={value, 1}; 47 fm[1].push_back(key); 48 mIter[key]=--fm[1].end(); 49 minFreq=1; 50 size++; 51 } 52 };
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 Increasing frequencies 2 -----------------------------> 3 4 +------+ +---+ +---+ +---+ 5 | Head |----| 1 |----| 5 |----| 9 | Frequencies 6 +------+ +-+-+ +-+-+ +-+-+ 7 | | | 8 +-+-+ +-+-+ +-+-+ | 9 |2,3| |4,3| |6,2| | 10 +-+-+ +-+-+ +-+-+ | Most recent 11 | | | 12 +-+-+ +-+-+ | 13 key,value pairs |1,2| |7,9| | 14 15 16 17 class LFUCache 18 { 19 public: 20 struct LRUNode 21 { 22 int freq; 23 list<pair<int, int> > vals; 24 LRUNode(int f = 0) : freq(f) { } 25 }; 26 27 typedef list<LRUNode>::iterator iptr; 28 typedef list<pair<int, int> >::iterator jptr; 29 30 LFUCache(int capacity) 31 { 32 capacity_ = capacity; 33 } 34 35 int get(int key) 36 { 37 int val = -1; 38 if (kv_.find(key) != kv_.end()) { 39 kv_[key] = promote(key); 40 val = kv_[key].second->second; 41 } 42 return val; 43 } 44 45 void set(int key, int value) 46 { 47 if (capacity_ <= 0) return; 48 if (kv_.find(key) == kv_.end()) { 49 if (kv_.size() == capacity_) evict(); 50 kv_[key] = insert(key, value); 51 } else { 52 kv_[key] = promote(key, value); 53 } 54 } 55 56 private: 57 pair<iptr, jptr> promote(int key, int val = -1) 58 { 59 iptr i; jptr j; 60 tie(i, j) = kv_[key]; 61 iptr k = next(i); 62 63 if (val < 0) val = j->second; 64 int freq = i->freq + 1; 65 66 i->vals.erase(j); 67 if (i->vals.empty()) 68 cache_.erase(i); 69 70 if (k == cache_.end() || k->freq != freq) 71 i = cache_.insert(k, LRUNode(freq)); 72 else i = k; 73 j = i->vals.insert(i->vals.end(), {key, val}); 74 return {i, j}; 75 } 76 77 void evict() 78 { 79 iptr i = cache_.begin(); 80 jptr j = i->vals.begin(); 81 kv_.erase(j->first); 82 i->vals.erase(j); 83 if (i->vals.empty()) 84 cache_.erase(i); 85 } 86 87 pair<iptr, jptr> insert(int key, int val) 88 { 89 iptr i = cache_.begin(); 90 if (i == cache_.end() || i->freq != 1) 91 i = cache_.insert(i, LRUNode(1)); 92 jptr j = i->vals.insert(i->vals.end(), {key, val}); 93 return {i, j}; 94 } 95 96 private: 97 list<LRUNode> cache_; 98 int capacity_; 99 unordered_map<int, pair<iptr, jptr> > kv_; 100 };
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 class LFUCache { 2 public: 3 struct Node { 4 int key; // key of the element. 5 int val; // value of the ement. 6 int fre; // usage frequency 7 int timeStamp; // the latest time stamp when this element is accessed. 8 Node(): key(-1), val(-1), timeStamp(-1), fre(0) {} 9 Node(int k, int v, int ts): key(k), val(v), timeStamp(ts), fre(1) {} 10 }; 11 12 LFUCache(int capacity) { 13 Cap = capacity; 14 Node* dummy = new Node(); 15 pq.push_back(dummy); // The pq start from pq[1]. 16 ts = 0; 17 } 18 19 int get(int key) { 20 if(!mp.count(key)) return -1; 21 int index = mp[key]; 22 int val = pq[index]->val; 23 pq[index]->fre++; 24 pq[index]->timeStamp = ++ts; 25 sink(index); 26 return val; 27 } 28 29 void set(int key, int value) { 30 if(Cap <= 0) return; 31 if(mp.count(key)) { 32 int index = mp[key]; 33 pq[index]->val = value; 34 get(key); 35 } 36 else { 37 if(pq.size() - 1 == Cap) { 38 int oldKey = pq[1]->key; 39 mp.erase(oldKey); 40 Node* newnode = new Node(key, value, ++ts); 41 pq[1] = newnode; 42 mp[key] = 1; 43 sink(1); 44 } 45 else { 46 Node* newnode = new Node(key, value, ++ts); 47 pq.push_back(newnode); 48 mp[key] = pq.size() - 1; 49 swim(pq.size() - 1); 50 } 51 } 52 } 53 54 private: 55 vector<Node*> pq; // A priority queue, with the least usage frequency and least recently used element at the top. 56 unordered_map<int, int> mp; // A mapping from the key of the element to its index in the priority queue. 57 int Cap; // Capcity of the cache 58 int ts; // time-stamp: indicate the time stamp of the latest operation of an element. According to the requirement of LFU cache, when we need to evict an element from the cache, but there are multiple elements with the same minimum frequency, then the least recently used element should be evicted. 59 60 /* 61 * Recursively sink a node in priority queue. A node will be sinked, when its frequency is larger than any of its 62 * children nodes, or the node has the same frequency with a child, but it is recently updated. 63 */ 64 void sink(int index) { 65 int left = 2 * index, right = 2 * index + 1, target = index; 66 if(left < pq.size() && pq[left]->fre <= pq[target]->fre) // If the left child has the same frequency, we probably need to swap the parent node and the child node, because the parent node is recently accessed, and the left child node was accessed at an older time stamp. 67 target = left; 68 if(right < pq.size()) { 69 if(pq[right]->fre < pq[target]->fre || (pq[right]->fre == pq[target]->fre && pq[right]->timeStamp < pq[target]->timeStamp)) // If right child has the same frequency and an older time stamp, we must swap it. 70 target = right; 71 } 72 if(target != index) { 73 myswap(target, index); 74 sink(target); 75 } 76 } 77 78 /*a 79 * Recursively swim a node in priority queue. A node will be swimmed, when its frequency is less than its 80 * parent node. If the node has the same frequency with its parent, it is not needed to be swimmed, because 81 * it is recently accessed. 82 */ 83 void swim(int index) { 84 int par = index / 2; 85 while(par > 0 && pq[par]->fre > pq[index]->fre) { 86 myswap(par, index); 87 index = par; 88 par /= 2; 89 } 90 } 91 92 void myswap(int id1, int id2) { 93 swap(pq[id1], pq[id2]); 94 mp[pq[id1]->key] = id1; 95 mp[pq[id2]->key] = id2; 96 } 97 };
split string in C
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#include <string> #include <sstream> #include <vector> #include <iterator> template<typename Out> void split(const std::string &s, char delim, Out result) { std::stringstream ss(s); std::string item; while (std::getline(ss, item, delim)) { *(result++) = item; } } std::vector<std::string> split(const std::string &s, char delim) { std::vector<std::string> elems; split(s, delim, std::back_inserter(elems)); return elems; } // std::vector<std::string> x = split("one:two::three", ':'); // "one", "two", "", "three"
quicksort
1 template<typename T> 2 void qsort(T arr[], int l, int r) { 3 /* 4 * 功能:对数组升序快排,递归实现 5 * 参数:arr:带排序数组,l:数组首元素下标,r:数组末元素下标 6 * 返回值:无 7 */ 8 9 if (l >= r) return ; 10 11 int i = l, j = r; 12 13 T pivot = arr[l]; // 通常取第一个数为基准 14 15 while (i < j) { // i,j 相遇即退出循环 16 while (i < j && arr[j] >= pivot) j--; 17 arr[i] = arr[j]; // 从右向左扫描,将比基准小的数填到左边 18 while (i < j && arr[i] <= pivot) i++; 19 arr[j] = arr[i]; // 从左向右扫描,将比基准大的数填到右边 20 } 21 22 arr[i] = pivot; // 将 基准数 填回 23 24 qsort(arr, l, i - 1); // 以基准数为界左右分治 25 qsort(arr, i + 1, r); 26 }
诸神对凡人心生艳羡,厌倦天堂。