leetcode笔记
82. Remove Duplicates from Sorted List II
https://leetcode.com/problems/remove-duplicates-from-sorted-list-ii/
下面代码是自写hashmap版,练一下hashmap,用一般的map<int,int>红黑树map也能过。
1 /** 2 * Definition for singly-linked list. 3 * struct ListNode { 4 * int val; 5 * ListNode *next; 6 * ListNode(int x) : val(x), next(NULL) {} 7 * }; 8 */ 9 10 11 class MyHash { 12 static const int MAX = 123456; 13 static const int MOD = 123447; 14 static const int WHAT = 1237; 15 static const int INVALID = -1234478; 16 pair<int,int> a[MAX]; 17 bool used[MAX]; 18 int siz =0; 19 int myhash(int key){ 20 if(siz==MOD)return MOD; 21 int pos = key*WHAT%MOD; 22 while(pos<0)pos=-(pos+1); 23 while(used[pos] && a[pos].first!=key)pos = (pos+1)%MOD; 24 return pos; 25 } 26 public: 27 int insert(pair<int,int> kv){ 28 int pos = myhash(kv.first); 29 if(pos==MOD)return -1; 30 if(!used[pos]){ 31 used[pos]=true; 32 siz++; 33 } 34 a[pos] = kv; 35 return 0; 36 } 37 int get(int key){ 38 int pos = myhash(key); 39 if(a[pos].first==key)return a[pos].second; 40 else return INVALID; 41 } 42 43 void add(int key, int ad){ 44 int pos = myhash(key); 45 if(!used[pos]){ 46 insert(make_pair(key,0)); 47 } 48 a[pos].second+=ad; 49 } 50 }; 51 52 class Solution { 53 public: 54 ListNode* deleteDuplicates(ListNode* head) { 55 MyHash count; 56 ListNode* cur = head; 57 while(cur!=NULL){ 58 count.add(cur->val,1); 59 cur=cur->next; 60 } 61 ListNode newhead(0); 62 newhead.next = head; 63 cur=&newhead; 64 while(cur!=NULL){ 65 while(cur->next !=NULL && count.get(cur->next->val)>1){ 66 cur->next = cur->next->next; 67 } 68 cur = cur->next; 69 } 70 return newhead.next; 71 } 72 };
106. Construct Binary Tree from Inorder and Postorder Traversal
https://leetcode.com/problems/construct-binary-tree-from-inorder-and-postorder-traversal/
根据中序后序建树。
一般思想:后序里面越靠前面的越是根,找到中序的[st,ed]中最是根的,建个结点,再递归分支左结点、右结点。
进一步思想:每次找最是根的那个要找区间最值,能不能直接找到那个根?根据后序遍历的规律,左子树的点和右子树的点肯定是分开的两部分,左边和右边,其中每部分的最后一个就是那个子树的根节点。
1 /** 2 * Definition for a binary tree node. 3 * struct TreeNode { 4 * int val; 5 * TreeNode *left; 6 * TreeNode *right; 7 * TreeNode(int x) : val(x), left(NULL), right(NULL) {} 8 * }; 9 */ 10 class Solution { 11 map<int,int> mp; 12 TreeNode* build(vector<int>& inorder, vector<int>& postorder, int inst, int ined , int post, int poed){ 13 if(inst>ined || post>poed)return NULL; 14 int inmid = mp[postorder[poed]]; 15 TreeNode * ret = new TreeNode(inorder[inmid]); 16 ret->left = build(inorder, postorder, inst, inmid-1, post, post + ((inmid-1) - inst)); 17 ret->right = build(inorder, postorder, inmid+1, ined,poed - 1 - (ined - (inmid+1)),poed - 1); 18 return ret; 19 } 20 public: 21 TreeNode* buildTree(vector<int>& inorder, vector<int>& postorder) { 22 for(int i=0; i<inorder.size(); i++){ 23 mp[inorder[i]] = i; 24 } 25 return build(inorder, postorder, 0, inorder.size()-1, 0, postorder.size()-1); 26 } 27 };
130. Surrounded Regions
https://leetcode.com/problems/surrounded-regions/
给一个矩阵,有X有O,把不与边界相连的O fill成X。
宽搜。我深搜有的点RE了,可恶。
宽搜代码:
1 #include<bits/stdc++.h> 2 using namespace std; 3 class Solution { 4 const int gx[4] = {1,-1,0,0}; 5 const int gy[4] = {0,0,1,-1}; 6 int n; 7 int m; 8 void fill(vector<vector<char>>&board , int x, int y,char c){ 9 queue<int> qx; 10 queue<int> qy; 11 qx.push(x); 12 qy.push(y); 13 board[x][y] = c; 14 while(!qx.empty()){ 15 x = qx.front(); 16 y = qy.front(); 17 qx.pop(); 18 qy.pop(); 19 for(int i=0; i<4; i++){ 20 int xx = x+gx[i]; 21 int yy = y+gy[i]; 22 if(xx<0 || xx>=n || yy<0 || yy>=m)continue; 23 if(board[xx][yy]=='X'|| board[xx][yy]=='1')continue; 24 board[xx][yy] = c; 25 qx.push(xx); 26 qy.push(yy); 27 } 28 } 29 } 30 public: 31 void solve(vector<vector<char>>& board) { 32 if(board.empty())return; 33 n = board.size(); 34 m = board[0].size(); 35 for(int i=0; i<n; i++){ 36 for(int j=0; j<m; j++){ 37 if((i==0 || j==0|| i==n-1 || j==m-1)&&board[i][j]=='O'){ 38 fill(board, i, j,'1'); 39 } 40 } 41 } 42 for(int i=1; i<n-1; i++){ 43 for(int j=1; j<m-1; j++){ 44 if(board[i][j]=='O'){ 45 fill(board, i, j,'X'); 46 } 47 } 48 } 49 for(int i=0; i<n; i++){ 50 for(int j=0; j<m; j++){ 51 if(board[i][j]=='1'){ 52 board[i][j] = 'O'; 53 } 54 } 55 } 56 } 57 }; 58 59 int main(){ 60 vector<vector<char> >board ={{'O','O'},{'O','O'}}; 61 Solution so; 62 so.solve(board); 63 return 0; 64 }
137. Single Number II
https://leetcode.com/problems/single-number-ii/
好多数出现3次,只有一个数出现1次。
解法:https://discuss.leetcode.com/topic/22821/an-general-way-to-handle-all-this-sort-of-questions
代码:
1 class Solution { 2 public: 3 int singleNumber(vector<int>& nums) { 4 //00 01 10 5 //01 10 00 6 int a = 0; 7 int b = 0; 8 for(int x:nums){ 9 int na = (x & ~a & b) | (~x & a & ~b); 10 int nb = (x & ~b & ~a)| (~x & ~a & b); 11 a = na; 12 b = nb; 13 } 14 return ~a & b; 15 } 16 };
138. Copy List with Random Pointer
https://leetcode.com/problems/copy-list-with-random-pointer/
深拷贝带随机指针的链表。
不用额外空间的方法:把A->B->C 各个节点复制一份放在旁边,A->A`->B->B`->C->C`,然后x`->random = x`->random->next。然后再把这个拆成两个链表。
注意原来的链表不能破坏,要把它拆回原样。(我以为能随便乱搞,结果错了好久,可恶)
1 /** 2 * Definition for singly-linked list with a random pointer. 3 * struct RandomListNode { 4 * int label; 5 * RandomListNode *next, *random; 6 * RandomListNode(int x) : label(x), next(NULL), random(NULL) {} 7 * }; 8 */ 9 class Solution { 10 public: 11 RandomListNode *copyRandomList(RandomListNode *head) { 12 if(!head)return head; 13 RandomListNode *cur = head, *x,*t; 14 while(cur){ 15 t = cur->next; 16 x = new RandomListNode(cur->label); 17 x->next = t; 18 x->random = cur->random; 19 cur->next = x; 20 cur = t; 21 } 22 cur = head; 23 while(cur){ 24 cur = cur->next; 25 if(cur->random) cur->random = (cur->random)->next; 26 cur= cur->next; 27 } 28 x = head->next; 29 cur = head; 30 while(cur){ 31 t = cur->next; 32 cur->next = cur->next->next; 33 if(cur->next)t->next = cur->next->next; 34 else t->next = NULL; 35 cur = cur->next; 36 } 37 return x; 38 } 39 };
146. LRU Cache
https://leetcode.com/problems/lru-cache/
LRU。每次满的时候把最久没用的那个踢出去。
单链表+map,查找O(logn) 冲突O(n),因为要扫到最后一个。如果要冲突O(1)的话要双链表。
1 https://leetcode.com/problems/lru-cache/
双向链表,把插入和删除函数抽了出来,好像不错:
1 struct kvNode{ 2 int key; 3 int val; 4 kvNode *left, *right; 5 kvNode(int k,int v):key(k), val(v),left(NULL), right(NULL){}; 6 kvNode():key(0),val(0),left(NULL),right(NULL){}; 7 }; 8 class LRUCache{ 9 int cnt = 0; 10 int ma; 11 kvNode h,tail; 12 map<int,kvNode*> mp; 13 void insert(kvNode* f, kvNode* now){; 14 now->left = f; 15 now->right = f->right; 16 f->right->left = now; 17 f->right = now; 18 } 19 void del(kvNode* now){ 20 now->left->right = now->right; 21 now->right->left = now->left; 22 } 23 public: 24 LRUCache(int capacity) { 25 ma = capacity; 26 h.right=&tail; 27 tail.left = &h; 28 mp.clear(); 29 } 30 31 int get(int key) { 32 if(mp.find(key)!=mp.end()){ 33 kvNode *p = mp[key]; 34 del(p); 35 insert(&h, p); 36 return p->val; 37 } 38 return -1; 39 } 40 41 void set(int key, int value) { 42 if(ma==0)return; 43 if(mp.find(key)==mp.end()){ 44 if(cnt==ma){ 45 kvNode *q = tail.left; 46 mp.erase(q->key); 47 del(q); 48 delete q; 49 cnt--; 50 } 51 kvNode *p = new kvNode(key,value); 52 insert(&h,p); 53 mp[key] = p; 54 cnt++; 55 }else{ 56 kvNode *p = mp[key]; 57 p->val = value; 58 del(p); 59 insert(&h, p); 60 } 61 } 62 };
148. Sort List
https://leetcode.com/problems/sort-list/
链表排序。
当然是用归并排序啦!都不用开多少新的空间。
不过第一次写的时候,居然写错,可恶,有点难。
关键在于,比如把AB分为A和B两份,我们要先存A之前的那个点aa、B之后的那个点bb,排完以后要他们连起来, aa->排完的->bb。
为了更方便排,先要把他们切开,写一个split(node, length)函数,把node开始的length个结点之后变成null,把结尾之后的那个点返回。
这样,就很容易排了!
1 /** 2 * Definition for singly-linked list. 3 * struct ListNode { 4 * int val; 5 * ListNode *next; 6 * ListNode(int x) : val(x), next(NULL) {} 7 * }; 8 */ 9 class Solution { 10 ListNode* merge(ListNode* l, ListNode *r){ 11 ListNode temp(0); 12 ListNode *cur = &temp; 13 while(l && r){ 14 if(l->val < r->val){ 15 cur->next = l; 16 cur = l; 17 l = l->next; 18 }else{ 19 cur->next = r; 20 cur = r; 21 r=r->next; 22 } 23 } 24 if(l){ 25 cur->next = l; 26 }else cur->next = r; 27 cur = temp.next; 28 return cur; 29 } 30 31 ListNode *split(ListNode *st, int w){ 32 for(int i=1;st&& i<w; i++)st = st->next; 33 if(st==NULL)return NULL; 34 ListNode *p = st->next; 35 st->next = NULL; 36 return p; 37 } 38 public: 39 ListNode* sortList(ListNode* head) { 40 ListNode temp(0); 41 ListNode *hh = &temp; 42 hh->next = head; 43 int siz=0; 44 ListNode *cur = head; 45 while(cur){ 46 siz++; 47 cur=cur->next; 48 } 49 for(int w=1; w<=siz; w*=2){ 50 ListNode *tail = hh, *mid,*r; 51 while(tail->next){ 52 mid = split(tail->next,w); 53 r = split(mid,w); 54 tail->next = merge(tail->next, mid); 55 for(int i=0;(tail->next)&& i<2*w; i++){ 56 tail = tail->next; 57 } 58 tail->next = r; 59 } 60 } 61 return hh->next; 62 } 63 };
168. Excel Sheet Column Title
171. Excel Sheet Column Number
https://leetcode.com/problems/excel-sheet-column-title/
https://leetcode.com/problems/excel-sheet-column-number/
168是列数转excel列号,1对应A,27对应AA。
171是反过来转,excel列号转列数。
解:因为这个和进制有一点差别,没法直接把字母当做26进制,只好认真观察,瞪眼法。
观察草稿:
1 A 1 Z 26 2 AA 27 = 26+1 3 AZ 52 = 26 + 26 4 BA 53 = 26*2 + 1 5 ZA 26*26 + 1 6 ZZ 26*26 + 26 7 AAA 26*26 + 26 + 1 8 AZZ 26*26 + 26*26 + 26 9 10 AA AZ -> A Z (X-1)%26 11 AA AZ -> A (X-1) / 26 12 AAA AZZ -> AA AZ
168代码:
1 class Solution { 2 public: 3 string convertToTitle(int n) { 4 string ret = ""; 5 while(n){ 6 int x = (n-1)%26; 7 char c = 'A'+x; 8 ret = c+ret; 9 n = (n-1)/26; 10 } 11 return ret; 12 } 13 };
171代码:
1 class Solution { 2 public: 3 int titleToNumber(string s) { 4 int ans=0; 5 int bei=1; 6 for(int i = s.size()-1; i>=0; i--){ 7 int x = s[i]-'A' + 1; 8 ans += bei*x; 9 bei*=26; 10 } 11 return ans; 12 } 13 };
209. Minimum Size Subarray Sum
https://leetcode.com/problems/minimum-size-subarray-sum/
在数列中找 和大于等于s的连续子串 的最小长度。
1.求和不能每次都直接一个个加(O(n)),可以像我这样弄一个求和数组求(O(1)),或者在滑动窗口的时候维护(可能比较麻烦,求和数组比较直接)。
2.注意题目要求,如果没有满足需求的就返回0,包括数组为空的情况。
3.一顿滑动
4.补充:题目说做了O(n)的还要试试O(nlogn)的……what?看了别人的答案,O(n)的一般是滑动窗口不用求和数组,这样空间O(1)。O(nlogn)的是二分+求和数组的。
O(n):
1 class Solution { 2 public: 3 vector<int> a; 4 int sum(int st, int ed){ 5 return a[ed+1] - a[st]; 6 } 7 8 int minSubArrayLen(int s, vector<int>& nums) { 9 int siz = nums.size(); 10 while(!a.empty())a.pop_back(); 11 a.push_back(0); 12 for(int i=0; i<siz; i++) 13 a.push_back(a[i] + nums[i]); 14 int r=0,l=0; 15 while(sum(l,r)<s && r<siz)r++; 16 if(r>=siz)return 0; 17 int ans = r-l+1; 18 for(;r<siz;r++){ 19 while(r>l && sum(l+1,r)>=s)l++; 20 ans = min(r-l+1, ans); 21 } 22 return ans; 23 } 24 };
O(nlogn):
1 #include<bits/stdc++.h> 2 using namespace std; 3 class Solution { 4 public: 5 vector<int> a; 6 int sum(int st, int ed) { 7 return a[ed+1] - a[st]; 8 } 9 10 int bs(int st,int ed, int s){ 11 int l=st, r=ed; 12 int re = INT_MAX; 13 while(l<=r){ 14 int mid = l + (r-l)/2; 15 if(sum(st,mid)>=s) 16 r=mid-1; 17 else l=mid+1; 18 } 19 if(l<=ed)re=l; 20 return re; 21 } 22 23 int minSubArrayLen(int s, vector<int>& nums) { 24 int siz = nums.size(); 25 while(!a.empty())a.pop_back(); 26 a.push_back(0); 27 for(int i=0; i<siz; i++) 28 a.push_back(a[i] + nums[i]); 29 int ans = INT_MAX; 30 for(int st=0; st<siz; st++){ 31 int x = bs(st,siz-1,s); 32 if(x!=INT_MAX) 33 ans = min(ans,x - st + 1); 34 } 35 return ans!=INT_MAX?ans:0; 36 } 37 }; 38 39 int main(){ 40 int s=7; 41 int arr[]={2,3,1,2,4,3}; 42 vector<int> v(arr,arr+6); 43 Solution so; 44 int ans = so.minSubArrayLen(s,v); 45 printf("%d\n",ans); 46 return 0; 47 }
211. Add and Search Word - Data structure design
https://leetcode.com/problems/add-and-search-word-data-structure-design/
做一个数据结构,支持插入字符串和判断字符串是否在,判断时支持用点.代替任意字母,其他的只能是a到z小写字母。
解:用字典树,遇到点的时候用26种递归去找。
1 class TrieNode{ 2 public: 3 bool isKey; 4 TrieNode* child[26]; 5 TrieNode():isKey(false){ 6 memset(child,NULL, sizeof(child)); 7 } 8 }; 9 10 class WordDictionary { 11 TrieNode root; 12 bool find(const char *s, TrieNode *cur){ 13 int j=0; 14 while(s[j]){ 15 char c = s[j]; 16 if(c!='.'){ 17 int q = c - 'a'; 18 if(cur->child[q]) cur = cur->child[q]; 19 else return false; 20 }else{ 21 for(int i=0; i<26; i++){ 22 if(cur->child[i]){ 23 if(find(s+j+1, cur->child[i])) return true; 24 } 25 } 26 return false; 27 } 28 j++; 29 } 30 if(cur->isKey)return true; 31 else return false; 32 } 33 public: 34 35 // Adds a word into the data structure. 36 void addWord(string word) { 37 TrieNode* cur = &root; 38 for(char c:word){ 39 int q = c - 'a'; 40 if(cur->child[q] == NULL){ 41 cur ->child[q] = new TrieNode(); 42 } 43 cur = cur->child[q]; 44 } 45 cur->isKey = true; 46 } 47 48 // Returns if the word is in the data structure. A word could 49 // contain the dot character '.' to represent any one letter. 50 bool search(string word) { 51 return find(word.c_str(), &root); 52 } 53 }; 54 55 // Your WordDictionary object will be instantiated and called as such: 56 // WordDictionary wordDictionary; 57 // wordDictionary.addWord("word"); 58 // wordDictionary.search("pattern");
227. Basic Calculator II
https://leetcode.com/problems/basic-calculator-ii/
表达式求值,加减乘除,不带括号。
可恶,看了题解,发现这个不带括号的直接瞎比做就行了,我还想什么栈方法什么递归方法想了半天,简直逗,题解都是只要十几行的。
下面是没看题解写的。
=============分割线============
随机到这题发现我真的弱,这是基础题啊,我都不记得怎么做,需要认真复习了。
方法两种:
1.先用一个符号栈中缀转后缀,再用一个操作数栈进行后缀表达式求值。
2.用两个栈,一个符号栈一个操作数栈,直接对中缀表达式求值。
中缀转后缀的代码:
1 class Solution { 2 map<char,int> priority; 3 int cal(vector<int> v){ 4 stack<int> s; 5 for(int x:v){ 6 if(x>=0)s.push(x); 7 else{ 8 char c = -x; 9 int z = s.top(); 10 s.pop(); 11 int y = s.top(); 12 s.pop(); 13 int w; 14 switch(c){ 15 case '+': 16 w = y+z; 17 break; 18 case '-': 19 w=y-z; 20 break; 21 case '*': 22 w=y*z; 23 break; 24 case '/': 25 w=y/z; 26 break; 27 } 28 s.push(w); 29 } 30 } 31 return s.top(); 32 } 33 34 vector<int> mid2back(vector<int> v){ 35 vector<int> ret; 36 stack<char> s; 37 for(int x:v){ 38 if(x>=0)ret.push_back(x); 39 else{ 40 char c = -x; 41 while(!s.empty() && priority[s.top()]>=priority[c]){ 42 ret.push_back(-s.top()); 43 s.pop(); 44 } 45 s.push(c); 46 } 47 } 48 while(!s.empty()){ 49 ret.push_back(-s.top()); 50 s.pop(); 51 } 52 return ret; 53 } 54 55 vector<int> str2vec(string s){ 56 vector<int> ret; 57 int num=0; 58 for(char c:s){ 59 if(c==' ')continue; 60 if(c>='0' && c<='9') num = num*10 + (c - '0'); 61 else { 62 ret.push_back(num); 63 num=0; 64 char ch = c; 65 ret.push_back(-c); 66 } 67 } 68 ret.push_back(num); 69 return ret; 70 } 71 72 public: 73 Solution(){ 74 priority['*']=2; 75 priority['/']=2; 76 priority['+']=1; 77 priority['-']=1; 78 } 79 80 int calculate(string s) { 81 vector<int> midexp = str2vec(s); 82 vector<int> backexp = mid2back(midexp); 83 int ans = cal(backexp); 84 return ans; 85 } 86 };
思考:如果带括号怎么做?中缀转后缀的时候就要将括号消掉了,遇到右括号就要疯狂出栈直到消掉左括号。难道是左右括号优先级1,加减2,乘除3?特殊处理弹出左括号的时候就结束while,并且右括号不入栈,好像不错。不对,这样入左括号的时候,之前的就要弹光了,难道左括号特殊处理不管优先级就进站?好像可以。
312. Burst Balloons
https://leetcode.com/problems/burst-balloons/
有一排乘法恐狼先锋,你杀一个i号狼会收到a[i-1]*a[i]*a[i+1]的伤害,然后剩下的会连起来。求能受到的最大伤害。
和hdu 5115 Dire Wolf 题解 (ACM/ICPC 14 北京站 现场赛) 差不多。别人的题解:http://blog.163.com/infog@126/blog/static/783768072014114714157/
区间DP代码:
1 class Solution { 2 public: 3 int maxCoins(vector<int>& nums) { 4 int f[nums.size()+1][nums.size()+1]; 5 memset(f,0,sizeof(f)); 6 int n=nums.size(); 7 for(int k=0; k<n; k++){ 8 for(int i=0; i+k<n; i++){ 9 int t=1; 10 if(i-1>=0)t*=nums[i-1]; 11 if(i+k+1<n)t*=nums[i+k+1]; 12 for(int j=i; j<=i+k; j++){ 13 f[i][i+k] = max(f[i][i+k], f[i][j-1] + f[j+1][i+k] + t*nums[j]); 14 } 15 } 16 } 17 return f[0][n-1]; 18 } 19 };
352. Data Stream as Disjoint Intervals
https://leetcode.com/problems/data-stream-as-disjoint-intervals/
做一个数据结构,支持插入数字,输出一堆区间。
用一个map记各个数字,指向Interval编号。
插入数字的时候维护区间左右端点, 合并区间的时候删Interval。
注意不仅要维护左右端点,当前插入点也要记一下,不然会重复插入,我这个错找了好久。
1 /** 2 * Definition for an interval. 3 * struct Interval { 4 * int start; 5 * int end; 6 * Interval() : start(0), end(0) {} 7 * Interval(int s, int e) : start(s), end(e) {} 8 * }; 9 */ 10 class SummaryRanges { 11 map<int,int> mp; 12 map<int,Interval>itv; 13 int n=0; 14 public: 15 /** Initialize your data structure here. */ 16 SummaryRanges() { 17 mp.clear(); 18 itv.clear(); 19 n=0; 20 } 21 22 void addNum(int val) { 23 if(mp.find(val)==mp.end()){ 24 int l =val; 25 int r = val; 26 if(mp.find(val-1)!=mp.end()) l = min(l, itv[mp[val-1]].start); 27 if(mp.find(val+1)!=mp.end()) r = max(r, itv[mp[val+1]].end); 28 if(l==r){ 29 itv[n] = Interval(val,val); 30 mp[val]=n; 31 n++; 32 }else if(l!=val && r!=val){ 33 itv.erase(mp[r]); 34 itv[mp[l]].start = l; 35 itv[mp[l]].end = r; 36 mp[r]=mp[l]; 37 mp[val]=mp[l];// use for judge if val insert before 38 }else{ 39 int x = (l==val)?r:l; 40 itv[mp[x]].start = l; 41 itv[mp[x]].end = r; 42 mp[val] = mp[x]; 43 } 44 } 45 } 46 47 static bool cmp(const Interval &x,const Interval &y){ 48 return x.start < y.start; 49 } 50 51 vector<Interval> getIntervals() { 52 vector<Interval> ret; 53 for(pair<int,Interval> it:itv){ 54 ret.push_back(it.second); 55 } 56 sort(ret.begin(), ret.end(), cmp); 57 return ret; 58 } 59 }; 60 61 /** 62 * Your SummaryRanges object will be instantiated and called as such: 63 * SummaryRanges obj = new SummaryRanges(); 64 * obj.addNum(val); 65 * vector<Interval> param_2 = obj.getIntervals(); 66 */
374. Guess Number Higher or Lower
https://leetcode.com/problems/guess-number-higher-or-lower/
幸运52猜数字,注意点:1.C++ 爆int,平均数要用x = l + (r-l)/2;
2.当l==r时就不用再猜一次了可以直接return。(不关键)
394. Decode String
https://leetcode.com/problems/decode-string/
递归:
1 class Solution { 2 string decode(string s, int &i){ 3 int cnt=0; 4 string ret = ""; 5 for(; s[i]!=']'; i++){ 6 if(s[i]>='0' && s[i]<='9'){ 7 cnt = cnt *10 + (s[i]-'0'); 8 }else if(s[i]=='['){ 9 i++; 10 string t = decode(s,i); 11 for(int j=0; j<cnt; j++) 12 ret += t; 13 cnt = 0; 14 }else ret += s[i]; 15 } 16 return ret; 17 } 18 public: 19 string decodeString(string s) { 20 int i=0; 21 return decode(s+"]", i); 22 } 23 };
非递归:
1 class Solution { 2 public: 3 string decodeString(string s) { 4 int i=0; 5 stack<int> si; 6 stack<string> ss; 7 string t=""; 8 int cnt = 0; 9 for(char c:s){ 10 if(c>='0' && c<='9'){ 11 cnt = cnt *10 + (c-'0'); 12 }else if(c=='['){ 13 si.push(cnt); 14 cnt=0; 15 ss.push(t); 16 t=""; 17 }else if(c==']'){ 18 cnt = si.top(); 19 si.pop(); 20 string tt = t; 21 t = ss.top(); 22 ss.pop(); 23 for(int j=0; j<cnt; j++) 24 t += tt; 25 cnt = 0; 26 }else t += c; 27 } 28 return t; 29 } 30 };
450. Delete Node in a BST
https://leetcode.com/problems/delete-node-in-a-bst/
删除二叉搜索树中的一点。又不用平衡,随便搞搞,虽然我搞错了好久……
1 /** 2 * Definition for a binary tree node. 3 * struct TreeNode { 4 * int val; 5 * TreeNode *left; 6 * TreeNode *right; 7 * TreeNode(int x) : val(x), left(NULL), right(NULL) {} 8 * }; 9 */ 10 class Solution { 11 int deleteLittle(TreeNode * cur){ 12 TreeNode * fa = cur; 13 while(cur->left!=NULL){ 14 fa = cur; 15 cur = cur->left; 16 } 17 int ret = cur->val; 18 fa->left = cur->right;//this, I wrote wrong : fa->left = NULL, ouch! spend much time to find and fix it. 19 return ret; 20 } 21 public: 22 TreeNode* deleteNode(TreeNode* root, int key) { 23 if(!root)return NULL; 24 if(root->val ==key){ 25 if(!root->left)return root->right; 26 if(!root->right)return root->left; 27 if((root->right)->left!=NULL){ 28 root->val = deleteLittle(root->right); 29 }else{ 30 root->val = root->right->val; 31 root->right = root->right->right; 32 } 33 }else{ 34 if(key < root->val){ 35 root->left = deleteNode(root->left, key); 36 }else 37 root->right = deleteNode(root->right, key); 38 } 39 return root; 40 } 41 };
460. LFU Cache
https://leetcode.com/problems/lfu-cache/
LFU,Least Frequently Used (LFU) ,是冲突时先删频率最小的,频率相同的话删最久没用过的。(另外一种叫LRU,就是删最久没用过的)。
做完发现怎么是hard,可恶,不过复习了LRU LFU的概念。
这个关键是,冲突时怎么找到最小的那个。每次冲突都要找最小的,很容易想到需要一个能够支持插入、删除、快速找到最小的这三中操作的数据结构,这不就是,map嘛,底层是红黑树实现,插入删除查找都是Logn,无敌。如果是每次在数组里扫最小的,那是O(n)。
另外用key找value,这个我也用的map,总的时间复杂度大概,查找是logn,插入时冲突,也是logn,好像是这个样子,每次操作logn,m次操作mlogn。
题目提示说要O(1)操作,那key找value可以hash,这个找最小要怎么O(1)?等我想一想。
logn代码:
1 class LFUCache { 2 int capa; 3 int used; 4 typedef pair<pair<int,int>,pair<int,int> > p4i;// frequency, time, key, value 5 vector<p4i> v; //v[pos] 6 map<int,int> mp; //<key, pos> 7 map<pair<int,int>, int> freqTimePos; // frequency, time , pos 8 int time; 9 public: 10 LFUCache(int capacity) { 11 capa = capacity; 12 used=0; 13 time=0; 14 v.clear(); 15 mp.clear(); 16 } 17 18 int get(int key) { 19 if(mp.find(key)!=mp.end()){ 20 time++; 21 int p = mp[key]; 22 freqTimePos.erase(v[p].first); 23 v[p].first.second = time; 24 v[p].first.first++; 25 freqTimePos[v[p].first]=p; 26 return v[p].second.second; 27 }else return -1; 28 } 29 30 void put(int key, int value) { 31 time++; 32 if(mp.find(key)!=mp.end()){ 33 int p = mp[key]; 34 freqTimePos.erase(v[p].first); 35 v[p].first.second = time; 36 v[p].first.first++; 37 freqTimePos[v[p].first]=p; 38 v[p].second.second = value; 39 }else{ 40 if(used<capa){ 41 used++; 42 v.push_back(make_pair(make_pair(1,time),make_pair(key,value))); 43 freqTimePos[v.back().first]=v.size()-1; 44 mp[key]=v.size()-1; 45 }else{ 46 if(capa==0)return; 47 int ekey,epos; 48 map<pair<int,int>, int>::iterator it = freqTimePos.begin(); 49 epos = it->second; 50 ekey = v[epos].second.first; 51 mp.erase(ekey); 52 mp[key]=epos; 53 freqTimePos.erase(v[epos].first); 54 v[epos] = make_pair(make_pair(1,time),make_pair(key,value)); 55 freqTimePos[v[epos].first]=epos; 56 } 57 } 58 } 59 }; 60 61 /** 62 * Your LFUCache object will be instantiated and called as such: 63 * LFUCache obj = new LFUCache(capacity); 64 * int param_1 = obj.get(key); 65 * obj.put(key,value); 66 */