Sword finger offer brush questions
03 [duplicate number in array]
class Solution { public: int findRepeatNumber(vector<int>& nums) { sort(nums.begin(),nums.end()); for(int i=0;i<nums.size();i++) { if(nums[i+1]==nums[i]) { //cout<<nums[i]<<endl; //break; return nums[i]; } } return 0; } };
04 [find in 2D array]
class Solution { public: bool findNumberIn2DArray(vector<vector<int>>& matrix, int target) { if(matrix.empty()) return false; if(matrix[0].empty()) return false; int m = matrix.size(); int n = matrix[0].size(); for(int i=0;i<m;i++) { if(matrix[i][0]<=target&&matrix[i][n-1]>=target) { for(int j=0;j<n;j++) { if(matrix[i][j]==target) return true; } } } return false; } };
05 [replace spaces]
class Solution { public: string replaceSpace(string s) { vector<int> place; for(int i=0;i<s.size();i++) { if(s[i] == ' ') { place.push_back(i); } } for(auto it=place.rbegin();it!=place.rend();it++) { int i = *it; s[i] = '%'; s.insert(i+1,"20"); } return s; } };
Insert is to insert before pos.
06 [print linked list from end to end]
/** * Definition for singly-linked list. * struct ListNode { * int val; * ListNode *next; * ListNode(int x) : val(x), next(NULL) {} * }; */ class Solution { public: vector<int> reversePrint(ListNode* head) { int count = 0; auto tmp = head; while(tmp!=NULL) { count++; tmp = tmp->next; } vector<int> result(count,0); tmp = head; while(tmp!=NULL) { result[--count] = tmp->val; tmp = tmp->next; } return result; } };
07 [rebuild binary tree]
/** * Definition for a binary tree node. * struct TreeNode { * int val; * TreeNode *left; * TreeNode *right; * TreeNode(int x) : val(x), left(NULL), right(NULL) {} * }; */ TreeNode* recursion(vector<int>& preorder,int p1,int p2,vector<int>& inorder,int q1,int q2) { if(p1>p2||q1>q2) return NULL; TreeNode* newNode = new TreeNode(preorder[p1]); int leftTreeLen; for(int i=q1;i<=q2;i++) { if(preorder[p1] == inorder[i]) { leftTreeLen = i-q1; break; } } //Recursive left subtree TreeNode* leftNode = recursion(preorder, p1+1, p1+leftTreeLen,inorder, q1, q1+leftTreeLen-1); newNode->left = leftNode; //Recursive right subtree TreeNode* rightNode = recursion(preorder, p1+leftTreeLen+1, p2,inorder, q1+leftTreeLen+1, q2); newNode->right = rightNode; return newNode; } class Solution { public: TreeNode* buildTree(vector<int>& preorder, vector<int>& inorder) { TreeNode* root; root = recursion(preorder,0,preorder.size()-1,inorder,0,inorder.size()-1); return root; } };
If you want to string the tree, you can return the root node to the upper layer during recursion.
09 [implement queue with two stacks]
class CQueue { public: stack<int> s1,s2; CQueue() { } void appendTail(int value) { s1.push(value); } int deleteHead() { if(s2.empty()) { if(s1.empty()) return -1; while(!s1.empty()) { s2.push(s1.top()); s1.pop(); } } int tmp = s2.top(); s2.pop(); return tmp; } }; /** * Your CQueue object will be instantiated and called as such: * CQueue* obj = new CQueue(); * obj->appendTail(value); * int param_2 = obj->deleteHead(); */
10-I [Fibonacci sequence]
class Solution { public: int fib(int n) { int f0 = 0; int f1 = 1; int tmp; if(n==0) return f0; for(int i=0;i<n-1;i++) { //cout<<f1<<endl; tmp = (f0+f1)%1000000007; f0 = f1; f1 = tmp; } //cout<<f1<<endl; return f1; } };
The main examination questions should be serious, and attention should be paid to mold taking.
10-II [frog jumping steps]
class Solution { public: int numWays(int n) { if(n<=1) return 1; int a1 = 1; int a2 = 2; int a; for(int i=0;i<n-2;i++) { a = (a1+a2)%1000000007; a1=a2; a2 = a; } return a2; } };
11 [minimum number of rotation array]
class Solution { public: int minArray(vector<int>& numbers) { int size = numbers.size(); for(int i=0;i<size-1;i++) { if(numbers[i+1]<numbers[i]) { return numbers[i+1]; } } return numbers[0]; } };
12 [path in matrix]
class Solution { int iMax,jMax; int size; vector<vector<bool>> b; vector<vector<char>> board1; string word1; public: bool recursion(int i,int j,int pos) { //cout<<"i=="<<i<<"j="<<j<<"pos="<<pos<<"size="<<size<<endl; if(pos==size-1) return true; if(i+1<iMax&&b[i+1][j]&&board1[i+1][j]==word1[pos+1]) { b[i+1][j] = false; if(recursion(i+1,j,pos+1)) return true; b[i+1][j] = true; } if(j+1<jMax&&b[i][j+1]&&board1[i][j+1]==word1[pos+1]) { //cout<<"position="<<pos<<endl; b[i][j+1] = false; if(recursion(i,j+1,pos+1)) return true; b[i][j+1] = true; } if(i-1>-1&&b[i-1][j]&&board1[i-1][j]==word1[pos+1]) { b[i-1][j] = false; if(recursion(i-1,j,pos+1)) return true; b[i-1][j] = true; } if(j-1>-1&&b[i][j-1]&&board1[i][j-1]==word1[pos+1]) { //cout<<"hahaha"<<endl; //cout<<"ij_1b"<<i<<j-1<<" "<<b[i][j-1]<<endl; b[i][j-1] = false; if(recursion(i,j-1,pos+1)) return true; b[i][j-1] = true; } return false; } bool exist(vector<vector<char>>& board, string word) { //cout<<"to here"<<endl; iMax = board.size(); jMax = board[0].size(); //cout<<"iMax="<<iMax<<"jMax"<<jMax<<endl; vector<bool> tmp(jMax,true); //cout<<"to here"<<endl; b.resize(iMax,tmp); board1 = board; word1 = word; size = word.size(); for(int i=0;i<iMax;i++) { for(int j=0;j<jMax;j++) { if(board[i][j]!=word[0]) continue; b[i][j] = false; //cout<<"ij="<<i<<" "<<j<<endl; if(recursion(i,j,0)) return true; b[i][j] = true; } } return false; } };
13 [range of motion of robot]
class Solution { int result; int digitSum(int i,int j) { int sum = 0; while(1) { sum = sum+i%10; if(i/10==0) break; i = i/10; } while(1) { sum = sum+j%10; if(j/10==0) break; j = j/10; } return sum; } int recursion(int i,int j,int m,int n,vector<vector<bool>> &vis) { if(i+1<m&&j<n&&vis[i+1][j]) { result++; vis[i+1][j] = false; recursion(i+1,j,m,n,vis); } if(i<m&&j+1<n&&vis[i][j+1]) { vis[i][j+1] = false; result++; recursion(i,j+1,m,n,vis); } return 0; } public: int movingCount(int m, int n, int k) { vector<vector<bool>> vis(m,vector<bool>(n,true)); result = 1; for(int i=0;i<m;i++) { for(int j=0;j<n;j++) { if(digitSum(i,j)>k) { vis[i][j] = false; } } } recursion(0,0,m,n,vis); return result; } };
Remember to find a matrix to record where you have passed.
14-I [cut the rope]
class Solution { public: int cuttingRope(int n) { vector<int> dp(n+1); dp[2] = 1; for(int i=3;i<n+1;i++) { for(int j=1;j<=i-j;j++) { //cout<<i<<endl; //cout<<j<<endl; dp[i] = max(dp[i],j*dp[i-j]); dp[i] = max(dp[i],j*(i-j)); } } return dp[n]; } };
Learn to use simple enumeration to find the law of dynamic programming.
14-II [cut rope II]
class Solution { int mypow(int a,int n,int base) { long int tmp = base; for(int i=0;i<n;i++) { tmp = tmp*a; tmp = tmp%1000000007; } return tmp; } public: int cuttingRope(int n) { if(n==2) return 1; if(n==3) return 2; int num = ceil(n/3.0); int rem = n%3; int r; if(rem==0) { r = (mypow(3,num,1)); } else if(rem==1) { r = mypow(3,num-2,4); } else{ r = mypow(3,num-1,2); } return r; } };
The problem of cutting rope is always better to cut it into a length of 3 as far as possible. If necessary, cut it into equal lengths as much as possible.
INT_MAX = 2147483647 (ten digits)
INT_MIN = -2147483648 (ten digits)
So: int -2147483648 ~ 2147483647
Int is not enough. long int is usually enough.
15 [number of 1 in binary]
class Solution { public: int hammingWeight(uint32_t n) { int count = 0; int rem; while(1) { rem = n%2; if(rem==1) { count++; } n = n/2; if(n==0) break; } return count; } };
16 [integer power of value]
class Solution { public: double myPow(double x, int n) { if(x==1) return x; double r = 1; int k=n>0?n:-n; for(int i=0;i<k;i++) { r = r*x; } cout<<r<<endl; if(n<0) { r = 1.0/r; } cout<<r<<endl; return r; } };
Timeout version.
class Solution { public: double myPow(double x, int n) { if(x==1) return 1; if(x == 0) return 0; double res = 1; long int k = (long int)(n); if(n < 0) { x = 1/x; k = -k; } //cout<<k<<" "<<x<<endl; while(k!=0) { if(k%2) { res*=x; } x*=x; k>>=1; } return res; } };
The idea of turning x into x^2. If n is an odd number, first give it to rem.
17 [print from 1 to maximum n digits] math
class Solution { public: vector<int> printNumbers(int n) { int M = pow(10,n)-1; vector<int> res(M); for(int i=1;i<=M;i++) { res[i-1] = i; } return res; } };
18 [delete node of linked list]
/** * Definition for singly-linked list. * struct ListNode { * int val; * ListNode *next; * ListNode(int x) : val(x), next(NULL) {} * }; */ class Solution { public: ListNode* deleteNode(ListNode* head, int val) { if(head->val==val) return head->next; ListNode* cur = head; ListNode* curLast = NULL; while(1) { if(cur->val==val) { //cout<<cur->val<<endl; curLast->next = cur->next; break; } else { curLast = cur; cur = cur->next; } } return head; } };
19 [regular expression matching]
class Solution { public: bool isMatch(string s, string p) { int m = s.size(); int n = p.size(); vector<vector<int>> f(m+1,vector<int>(n+1)); f[0][0] = true; for(int i=0;i<n;i++) { if(p[i]=='*'&&(i==1||(i>=2&&f[0][i-1]))) { f[0][i+1] = true; } } if(n>0&&p[1]=='*') { f[0][2] = true; } int ii,jj; for(int i=0;i<m;i++) { for(int j=0;j<n;j++) { // cout<<"i="<<i<<"j="<<j<<endl; ii = i+1; jj = j+1; // cout<<"here1"<<endl; if(p[j]!='*') { if(p[j]=='.'||p[j]==s[i]) { // cout<<"here2"<<endl; f[ii][jj] = f[ii-1][jj-1]; // cout<<"here3"<<endl; } } else { //cout<<"here3"<<endl; if(f[ii][jj-2]) { f[ii][jj] = true; } else { if((p[j-1]=='.'||p[j-1]==s[i])&&f[ii-1][jj]) { f[ii][jj] = true; } } } } } // cout<<"here4"<<endl; return f[m][n]; } };
20 [string representing numeric value]
class Solution { public: enum State { STATE_INITIAL, STATE_INT_SIGN, STATE_INTEGER, STATE_POINT, STATE_POINT_WITHOUT_INT, STATE_FRACTION, STATE_EXP, STATE_EXP_SIGN, STATE_EXP_NUMBER, STATE_END }; enum CharType { CHAR_NUMBER, CHAR_EXP, CHAR_POINT, CHAR_SIGN, CHAR_SPACE, CHAR_ILLEGAL }; CharType toCharType(char ch) { if (ch >= '0' && ch <= '9') { return CHAR_NUMBER; } else if (ch == 'e' || ch == 'E') { return CHAR_EXP; } else if (ch == '.') { return CHAR_POINT; } else if (ch == '+' || ch == '-') { return CHAR_SIGN; } else if (ch == ' ') { return CHAR_SPACE; } else { return CHAR_ILLEGAL; } } bool isNumber(string s) { unordered_map<State, unordered_map<CharType, State>> transfer{ { STATE_INITIAL, { {CHAR_SPACE, STATE_INITIAL}, {CHAR_NUMBER, STATE_INTEGER}, {CHAR_POINT, STATE_POINT_WITHOUT_INT}, {CHAR_SIGN, STATE_INT_SIGN} } }, { STATE_INT_SIGN, { {CHAR_NUMBER, STATE_INTEGER}, {CHAR_POINT, STATE_POINT_WITHOUT_INT} } }, { STATE_INTEGER, { {CHAR_NUMBER, STATE_INTEGER}, {CHAR_EXP, STATE_EXP}, {CHAR_POINT, STATE_POINT}, {CHAR_SPACE, STATE_END} } }, { STATE_POINT, { {CHAR_NUMBER, STATE_FRACTION}, {CHAR_EXP, STATE_EXP}, {CHAR_SPACE, STATE_END} } }, { STATE_POINT_WITHOUT_INT, { {CHAR_NUMBER, STATE_FRACTION} } }, { STATE_FRACTION, { {CHAR_NUMBER, STATE_FRACTION}, {CHAR_EXP, STATE_EXP}, {CHAR_SPACE, STATE_END} } }, { STATE_EXP, { {CHAR_NUMBER, STATE_EXP_NUMBER}, {CHAR_SIGN, STATE_EXP_SIGN} } }, { STATE_EXP_SIGN, { {CHAR_NUMBER, STATE_EXP_NUMBER} } }, { STATE_EXP_NUMBER, { {CHAR_NUMBER, STATE_EXP_NUMBER}, {CHAR_SPACE, STATE_END} } }, { STATE_END, { {CHAR_SPACE, STATE_END} } } }; int len = s.length(); State st = STATE_INITIAL; for (int i = 0; i < len; i++) { CharType typ = toCharType(s[i]); if (transfer[st].find(typ) == transfer[st].end()) { return false; } else { st = transfer[st][typ]; } } return st == STATE_INTEGER || st == STATE_POINT || st == STATE_FRACTION || st == STATE_EXP_NUMBER || st == STATE_END; } };
It's easier to read this question than to do it. Copy the answer. Finite state automata is used. In short, it is to judge each bit. On each bit, judge what the next bit of this bit looks like to be true. If it is not satisfied, it is directly false. If it is satisfied, it is transferred to the next bit for judgment.
21 [adjust array order so that odd numbers precede even numbers]
class Solution { public: vector<int> exchange(vector<int>& nums) { vector<int> result,rest; for(auto &it:nums) { if(it%2) { result.push_back(it); } else { rest.push_back(it); } } for(auto &it:rest){result.push_back(it);}; return result; } };
22 [the penultimate node in the lin k ed list]
/** * Definition for singly-linked list. * struct ListNode { * int val; * ListNode *next; * ListNode(int x) : val(x), next(NULL) {} * }; */ class Solution { public: ListNode* getKthFromEnd(ListNode* head, int k) { int count = 1; auto cur = head; while(1) { if(cur->next!=NULL) { count++; cur = cur->next; } else { break; } } int s = count+1-k; cur = head; for(int i=0;i<s-1;i++) { cur = cur->next; } return cur; } };
24 [reverse linked list]
/** * Definition for singly-linked list. * struct ListNode { * int val; * ListNode *next; * ListNode(int x) : val(x), next(NULL) {} * }; */ class Solution { public: ListNode* reverseList(ListNode* head) { if(head==NULL) return NULL; if(head->next==NULL) return head; ListNode* cur = head; ListNode* next = cur->next; ListNode* last = NULL; ListNode* nextNext=next->next; while(1) { //cout<<cur->val<<endl; cur->next = last; if(next!=NULL) next->next = cur; //cout<<"cur"<<cur->val<<"next"<<next->val<<endl;//<<"last"<<last->val<<endl; last = cur; cur = next; if(cur==NULL) break; next = nextNext; if(next!=NULL) nextNext = next->next; } return last; } };
Four points are recorded.
25 [merge two sorted linked lists]
/** * Definition for singly-linked list. * struct ListNode { * int val; * ListNode *next; * ListNode(int x) : val(x), next(NULL) {} * }; */ class Solution { public: ListNode* mergeTwoLists(ListNode* l1, ListNode* l2) { if(l1==NULL) return l2; if(l2==NULL) return l1; ListNode* head = new ListNode; ListNode* cur1(head); ListNode* cur2(head); if(l1->val<l2->val) { head = l1; cur1 = l1->next; cur2 = l2; } else { head = l2; cur2 = l2->next; cur1 = l1; } auto cur = head; while(1) { if(cur1==NULL) { cur->next=cur2; return head; } if(cur2==NULL) { cur->next = cur1; return head; } if(cur1->val<cur2->val) { cur->next = cur1; cur1 = cur1->next; cur = cur->next; } else { cur->next = cur2; cur2 = cur2->next; cur = cur->next; } } return head; } };
Only when the contents of the things pointed to by the defined linked list are the same can they be assigned to each other.
26 [substructure of tree]
/** * Definition for a binary tree node. * struct TreeNode { * int val; * TreeNode *left; * TreeNode *right; * TreeNode(int x) : val(x), left(NULL), right(NULL) {} * }; */ class Solution { public: bool recursion(TreeNode* A, TreeNode* B) { if(A==NULL&&B!=NULL) return false; if(B==NULL) return true; return (A->val==B->val)&&recursion(A->left,B->left)&&recursion(A->right,B->right); }; bool isSubStructure(TreeNode* A, TreeNode* B) { //cout<<"A val"<<A->val<<" "<<"B val"<<B->val<<endl; if(B==NULL) return false; if(A==NULL) return false; if(recursion(A,B)) return true; if(isSubStructure(A->left,B)) return true; if(isSubStructure(A->right,B)) return true; return false; }; };
27 [image of binary tree]
/** * Definition for a binary tree node. * struct TreeNode { * int val; * TreeNode *left; * TreeNode *right; * TreeNode(int x) : val(x), left(NULL), right(NULL) {} * }; */ class Solution { public: TreeNode* mirrorTree(TreeNode* root) { if(root==NULL) return root; auto tmp = root->left; root->left = root->right; root->right = tmp; mirrorTree(root->left); mirrorTree(root->right); return root; } };
28 [symmetric binary tree]
/** * Definition for a binary tree node. * struct TreeNode { * int val; * TreeNode *left; * TreeNode *right; * TreeNode(int x) : val(x), left(NULL), right(NULL) {} * }; */ class Solution { public: bool isSym(TreeNode* left,TreeNode* right) { if(left==NULL&&right==NULL) return true; if(left==NULL&&right!=NULL) return false; if(left!=NULL&&right==NULL) return false; return (left->val==right->val)&&isSym(left->left,right->right)&&isSym(left->right,right->left); } bool isSymmetric(TreeNode* root) { if(root==NULL) return true; auto left = root->left; auto right = root->right; return isSym(left,right); } };
29 [print matrix clockwise]
class Solution { vector<vector<int>> matrixG; vector<int> result; public: void printSq(int i,int len1,int len2) { if(len1==1) { for(int s=i;s<=i+len2-1;s++) { result.push_back(matrixG[i][s]); } return; } if(len2==1) { for(int s=i;s<=i+len1-1;s++) { result.push_back(matrixG[s][i]); } return; } int n1 = i+len1-1; int n2 = i+len2-1; for(int k=i;k<=n2-1;k++) { //cout<<matrixG[i][k]<<endl; result.push_back(matrixG[i][k]); } for(int k=i;k<=n1-1;k++) { //cout<<matrixG[k][n]<<endl; result.push_back(matrixG[k][n2]); } for(int k=n2;k>i;k--) { //cout<<matrixG[n-1][k]<<endl; result.push_back(matrixG[n1][k]); } for(int k=n1;k>i;k--) { //cout<<matrixG[k][i]<<endl; result.push_back(matrixG[k][i]); } } vector<int> spiralOrder(vector<vector<int>>& matrix) { matrixG = matrix; int len1,len2; int size1 = matrix.size(); if(size1==0) return result; int size2 = matrix[0].size(); for(int i=0;i<round(min(size1,size2)/2.0);i++) { len1 = size1-2*(i); len2 = size2-2*(i); printSq(i,len1,len2); } return result; } };
30 [stack containing min function]
class MinStack { stack<int> stk; public: /** initialize your data structure here. */ MinStack() { } void push(int x) { stk.push(x); } void pop() { stk.pop(); } int top() { return stk.top(); } int min() { int m = stk.top(); stack<int> tmp; while(!stk.empty()) { m = stk.top()<m?stk.top():m; tmp.push(stk.top()); stk.pop(); } while(!tmp.empty()) { stk.push(tmp.top()); tmp.pop(); } return m; } }; /** * Your MinStack object will be instantiated and called as such: * MinStack* obj = new MinStack(); * obj->push(x); * obj->pop(); * int param_3 = obj->top(); * int param_4 = obj->min(); */
This is a timeout version. A non timeout version is provided below.
class MinStack { stack<int> stk; stack<int> tmp; public: /** initialize your data structure here. */ MinStack() { // cout<<0<<endl; } void push(int x) { stk.push(x); if(tmp.empty()||x<=tmp.top()) { tmp.push(x); } // cout<<1<<endl; } void pop() { if(stk.top()==tmp.top()) tmp.pop(); stk.pop(); // cout<<2<<endl; } int top() { // cout<<3<<endl; return stk.top(); } int min() { // cout<<4<<endl; return tmp.top(); } }; /** * Your MinStack object will be instantiated and called as such: * MinStack* obj = new MinStack(); * obj->push(x); * obj->pop(); * int param_3 = obj->top(); * int param_4 = obj->min(); */
31 [stack push in and pop-up sequence]
class Solution { public: bool validateStackSequences(vector<int>& pushed, vector<int>& popped) { if(popped.size()==0) return true; stack<int> stk; int ind = 0; for(auto &it:pushed) { //cout<<it<<endl; stk.push(it); while(!stk.empty()&&stk.top()==popped[ind]) { //cout<<stk.top()<<endl; stk.pop(); ind++; //cout<<ind<<endl; if(ind==popped.size()) return true; } } return false; } };
32-I [print binary tree from top to bottom]
/** * Definition for a binary tree node. * struct TreeNode { * int val; * TreeNode *left; * TreeNode *right; * TreeNode(int x) : val(x), left(NULL), right(NULL) {} * }; */ class Solution { public: vector<int> levelOrder(TreeNode* root) { vector<int> res; if(root==NULL) return res; vector<TreeNode*> queue; queue.push_back(root); while(!queue.empty()) { auto node = queue[0]; queue.erase(queue.begin()); res.push_back(node->val); if(node->left!=NULL) queue.push_back(node->left); if(node->right!=NULL) queue.push_back(node->right); } return res; } };
32-II [print binary tree II from top to bottom]
/** * Definition for a binary tree node. * struct TreeNode { * int val; * TreeNode *left; * TreeNode *right; * TreeNode(int x) : val(x), left(NULL), right(NULL) {} * }; */ class Solution { public: vector<vector<int>> levelOrder(TreeNode* root) { vector<vector<int>> res; vector<int> layer; vector<TreeNode*> F1; vector<TreeNode*> F2; F1.push_back(root); while(!F1.empty()) { for(auto& it:F1) { if(it==NULL) continue; layer.push_back(it->val); F2.push_back(it->left); F2.push_back(it->right); } if(!layer.empty()) res.push_back(layer); layer.clear(); F1.clear(); F1 = F2; F2.clear(); } return res; } };
32-III [print binary tree III from top to bottom]
/** * Definition for a binary tree node. * struct TreeNode { * int val; * TreeNode *left; * TreeNode *right; * TreeNode(int x) : val(x), left(NULL), right(NULL) {} * }; */ class Solution { public: vector<vector<int>> levelOrder(TreeNode* root) { vector<vector<int>> res; vector<int> layer; vector<TreeNode*> F1; vector<TreeNode*> F2; F1.push_back(root); int i=0; while(!F1.empty()) { for(auto& it:F1) { if(it==NULL) continue; layer.push_back(it->val); F2.push_back(it->left); F2.push_back(it->right); } if(!layer.empty()) { if(i%2==1) reverse(layer.begin(),layer.end()); res.push_back(layer); } layer.clear(); F1.clear(); F1 = F2; F2.clear(); i++; } return res; } };
33 [post order traversal sequence of binary search tree]
class Solution { bool recursion(int i,int j,vector<int>& postorder) { if(i>=j) return true; int p = i; while(postorder[p]<postorder[j]) p++; int m = p; while(postorder[p]>postorder[j]) p++; return p==j&&recursion(i,m-1,postorder)&&recursion(m,j-1,postorder); } public: bool verifyPostorder(vector<int>& postorder) { return recursion(0, postorder.size() - 1,postorder); } };
The definition of binary search tree is that the left, middle and right become larger in turn. Find the key points according to the definition, and then judge the left and right subtrees.
34 [path with a value in binary tree]
/** * Definition for a binary tree node. * struct TreeNode { * int val; * TreeNode *left; * TreeNode *right; * TreeNode() : val(0), left(nullptr), right(nullptr) {} * TreeNode(int x) : val(x), left(nullptr), right(nullptr) {} * TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {} * }; */ class Solution { public: vector<vector<int>> result; void dfs(TreeNode* root,int target,vector<int> res,int sum) { if(root==NULL) return; sum+=root->val; res.push_back(root->val); if(root->left==NULL&&root->right==NULL&&sum==target) { //cout<<"sum"<<sum<<endl;//"root.val"<<root->val<<endl; result.push_back(res); return; } if(root->left==NULL&&root->right==NULL&&sum!=target) { return; } //cout<<"root.val"<<root->val<<endl; dfs(root->left,target,res,sum); dfs(root->right,target,res,sum); return; } vector<vector<int>> pathSum(TreeNode* root, int target) { vector<int> res; int sum = 0; dfs(root,target,res,sum); return result; } };
35 [copy of complex linked list]
/* // Definition for a Node. class Node { public: int val; Node* next; Node* random; Node(int _val) { val = _val; next = NULL; random = NULL; } }; */ class Solution { unordered_map<Node*, Node*> cachedNode; public: Node* copyRandomList(Node* head) { if(head==NULL) return NULL; auto cur = head; Node* vir = new Node(0); Node* oldNode = vir; while(1) { Node* newNode = new Node(cur->val); cachedNode[cur] = newNode; oldNode->next = newNode; cur = cur->next; oldNode = newNode; if(cur==NULL) break; } auto head1 = vir->next; cur = head1; auto cur1 = head; while(cur!=NULL) { cur->random = cachedNode[cur1->random]; cur = cur->next; cur1 = cur1->next; } return head1; } };
When building points, make a one-to-one mapping with the original chain.
36 [binary search tree and bidirectional linked list]
/* // Definition for a Node. class Node { public: int val; Node* left; Node* right; Node() {} Node(int _val) { val = _val; left = NULL; right = NULL; } Node(int _val, Node* _left, Node* _right) { val = _val; left = _left; right = _right; } }; */ class Solution { private: Node *pre, *head; void dfs(Node* cur) { if(cur == NULL) return; dfs(cur->left); if(pre != NULL) pre->right = cur; else head = cur; cur->left = pre; pre = cur; dfs(cur->right); } public: Node* treeToDoublyList(Node* root) { if(root == NULL) return NULL; dfs(root); head->left = pre; pre->right = head; return head; } };
The binary search tree is traversed into an ordered two-way linked list.
37 [serialized binary tree]
/** * Definition for a binary tree node. * struct TreeNode { * int val; * TreeNode *left; * TreeNode *right; * TreeNode(int x) : val(x), left(NULL), right(NULL) {} * }; */ class Codec { public: void rserialize(TreeNode* root, string& str) { if (root == NULL) { str += "None,"; } else { str += to_string(root->val) + ","; rserialize(root->left, str); rserialize(root->right, str); } } TreeNode* rdeserialize(list<string>& dataArray) { if (dataArray.front() == "None") { dataArray.erase(dataArray.begin()); return NULL; } TreeNode* root = new TreeNode(stoi(dataArray.front())); dataArray.erase(dataArray.begin()); root->left = rdeserialize(dataArray); root->right = rdeserialize(dataArray); return root; } string serialize(TreeNode* root) { string ret; rserialize(root, ret); cout<<ret<<endl; return ret; } TreeNode* deserialize(string data) { list<string> dataArray; string str; for (auto& ch : data) { if (ch == ',') { dataArray.push_back(str); str.clear(); } else { str.push_back(ch); } } if (!str.empty()) { dataArray.push_back(str); str.clear(); } return rdeserialize(dataArray); } }; // Your Codec object will be instantiated and called as such: // Codec codec; // codec.deserialize(codec.serialize(root));
Preorder traversal is easy to convert and recover between binary tree and string. The three traversals of depth first search always uniquely determine the structure of the tree.
38 [arrangement of strings]
class Solution { int size; vector<string> result; void recursion(string s,vector<bool> posUsed,string res) { if(res.size()==size) { result.push_back(res); return; } for(int i=0;i<size;i++) { if(posUsed[i]) continue; res.push_back(s[i]); posUsed[i] = true; recursion(s,posUsed,res); posUsed[i] = false; res.pop_back(); } } public: vector<string> permutation(string s) { size = s.size(); vector<bool> posUsed(size,false); string res; recursion(s,posUsed,res); sort(result.begin(), result.end()); result.erase(unique(result.begin(), result.end()), result.end()); return result; } };
unique can only work after sorting. Typical backtracking violent search.
39 [number appearing more than half times in the array]
Method 1: hash table (time) O ( n ) O(n) O(n), space O ( n ) O(n) O(n))
#include <iostream> #include<vector> #include<unordered_map> using namespace std; int main() { vector<int> a = { 1,2,3,2,2,2,5,4,2 }; int n = a.size(); unordered_map<int, int> M; for (int i = 0;i < n;i++) { M[a[i]]++; } for (auto& it : M) { if (it.second > n / 2) { cout << it.first << endl; } } return 0; }
Method 2: quick sorting + pruning (time) O ( n ) O(n) O(n))
#include <iostream> #include<vector> using namespace std; int swap(vector<int>& nums, int i, int j) { int tmp = nums[i]; nums[i] = nums[j]; nums[j] = tmp; return 0; } int qsort(vector<int>& nums, int left, int right) { if (left >= right) return 0; int std = nums[left]; int i = left; int j = right; while (1) { if (i >= j) break; while (1) { if (j <= i || nums[j] < std) break; j--; } while (1) { if (i >= j || nums[i] > std) break; i++; } if (i < j) swap(nums, i, j); } int n = nums.size(); swap(nums, left, j); if (abs(2 * j - n + 1) <= 1) return nums[j]; else if (j < n / 2) return qsort(nums, j + 1, right); else return qsort(nums, left, j - 1); return 0; } int main() { vector<int> nums = { 1,2,3,2,2,2,5,4,2 }; int result = qsort(nums, 0, nums.size() - 1); cout << result << endl; return 0; }
40 [minimum number of k]
class Solution { public: vector<int> getLeastNumbers(vector<int>& arr, int k) { sort(arr.begin(),arr.end()); vector<int> r(k); for(int i=0;i<k;i++) { r[i] = arr[i]; } return r; } };
Can I use sorting?
41 [median in data stream]
class MedianFinder { public: /** initialize your data structure here. */ priority_queue<int,vector<int>,greater<int>> maxHeap; priority_queue<int,vector<int>,less<int>> minHeap; MedianFinder() { } void addNum(int num) { if(maxHeap.size()==minHeap.size()) { maxHeap.push(num); minHeap.push(maxHeap.top()); maxHeap.pop(); } else { minHeap.push(num); maxHeap.push(minHeap.top()); minHeap.pop(); } } double findMedian() { if(minHeap.size()==maxHeap.size()) { return (maxHeap.top()+minHeap.top())/2.0; } else{ return minHeap.top(); } } }; /** * Your MedianFinder object will be instantiated and called as such: * MedianFinder* obj = new MedianFinder(); * obj->addNum(num); * double param_2 = obj->findMedian(); */
The idea of small top pile and large top pile.
priority_queue<int,vector,greater> maxHeap;
priority_queue<int,vector,less> minHeap;
42 [maximum sum of successive subarrays]
class Solution { public: int maxSubArray(vector<int>& nums) { int size = nums.size(); int m = nums[0]; for(int i=0;i<size;i++) { int s = 0; for(int j=i;j<size;j++) { s+=nums[j]; m = max(m,s); } } return m; } };
Timeout version.
class Solution { public: int maxSubArray(vector<int>& nums) { int pre = 0, M = nums[0]; for (auto &it: nums) { pre = max(pre + it, it); M = max(M, pre); } return M; } };
f(i) stands for the number ending with the ith number. Dynamic transfer method must find out what the amount of transfer is.
43 [number of occurrences of 1 in integers 1 ~ n]
class Solution { public: int countDigitOne(int n) { long long mulk = 1; int ans = 0; for (int k = 0; n >= mulk; ++k) { ans += (n / (mulk * 10)) * mulk + min(max(n % (mulk * 10) - mulk + 1, 0LL), mulk); mulk *= 10; } return ans; } };
Count each digit separately to find the law.
44 [a digit in a sequence of digits]
class Solution { public: int findNthDigit(int n) { if(n<10) return n; int k=1; n = n-10; while(1) { k++; if(n>=k*9*pow(10,k-1)) { n-=k*9*pow(10,k-1); } else { break; } } int p = n/k; int d = n%k; //cout<<"n="<<n<<"p="<<p<<"d="<<d<<endl; int result = pow(10,k-1)+p; result = result/pow(10,k-d-1); result = result%10; return result; } };
The subscript is unclear. Just think about it with a simple example.
45 Sort into the smallest array
class Solution { public: bool static cmp(string &x,string &y) { if(x+y<y+x) return true; return false; } string minNumber(vector<int>& nums) { vector<string> strs; string res; for(int i = 0; i < nums.size(); i++) strs.push_back(to_string(nums[i]));//to_string can convert numeric constants, including decimals, into strings sort(strs.begin(), strs.end(), cmp); for(int i = 0; i < strs.size(); i++) res.append(strs[i]);//Available + alternative return res; } };
The third parameter of sort needs to be static, otherwise an error will be reported.
46 [translate numbers into strings]
class Solution { public: int translateNum(int num) { vector<int> nums; while(1) { nums.push_back(num%10); num = num/10; if(num==0) break; } reverse(nums.begin(),nums.end()); int sz = nums.size(); vector<int> dp(sz+1); dp[0] = 1; dp[1] = 1; for(int i=2;i<=sz;i++) { dp[i] = dp[i-1]; if(nums[i-2]==1||(nums[i-2]==2&&nums[i-1]<=5)) { dp[i] +=dp[i-2]; } } return dp[sz]; } };
Typical dynamic programming problems.
47 [maximum value of gift] dynamic programming
class Solution { public: int maxValue(vector<vector<int>>& grid) { int m = grid.size(); int n = grid[0].size(); vector<vector<int>> dp(m,vector<int>(n)); //dp[0][0] = grid[0][0]; for(int i=0;i<m;i++) { for(int j=0;j<n;j++) { if(i==0&&j==0) { dp[i][j] = grid[i][j]; } else if(i==0) { dp[i][j] = dp[i][j-1]+grid[i][j]; } else if(j==0) { dp[i][j] = dp[i-1][j] + grid[i][j]; } else { dp[i][j] = max(dp[i-1][j],dp[i][j-1])+grid[i][j]; } } } return dp[m-1][n-1]; } };
48 [longest substring without duplicate characters]
class Solution { public: int lengthOfLongestSubstring(string s) { if(s=="") return 0; int sz = s.size(); vector<int> dp(sz); dp[0] = 1; int a = 0; int M = 1; for(int i=1;i<sz;i++) { int j; for(j = i-1;j>=a;j--) { if(s[j]==s[i]) { a = j; dp[i] = i-j; break; } //cout<<a<<" "<<j<<endl; } if(j<a) { //cout<<a<<" "<<j<<endl; //cout<<dp[i]<<" "<<dp[i-1]<<endl; dp[i] = dp[i-1]+1; M = max(dp[i],M); } } //for(auto &it:dp) //{ // cout<<"dp="<<it<<endl; //} return M; } };
The key of dynamic programming is to find the meaning of dp and the transfer equation. For this splicing type, you can generally consider the value ending with xx as dp.
49 [ugly number]
class Solution { public: int nthUglyNumber(int n) { vector<int> dp(n+1); dp[1] = 1; int p1 = 1,p2 = 1,p3 = 1; for(int i=2;i<=n;i++) { dp[i] = min(min(2*dp[p1],3*dp[p2]),5*dp[p3]); if(dp[i]==2*dp[p1]) { p1++; } if(dp[i]==3*dp[p2]) { p2++; } if(dp[i]==5*dp[p3]) { p3++; } } return dp[n]; } };
The pointer moves down one when the new one is equal to the other.
50 [first character that appears only once]
class Solution { public: char firstUniqChar(string s) { unordered_map<char,int> map; for(auto &it:s) { map[it]++; } for(auto &it:s) { if(map[it]==1) { return it; } } return ' '; } };
Hash table is easy to handle simple problems.
51 [reverse order pairs in array]
class Solution { int result = 0; int merge(vector<int> &nums,int left,int mid,int right) { //cout<<left<<" "<<mid<<" "<<right<<endl; vector<int> L(nums.begin()+left,nums.begin()+mid+1); vector<int> R(nums.begin()+mid+1,nums.begin()+right+1); //cout<<"Li="<<L[0]<<endl; //cout<<"Rj="<<R[0]<<endl; int i=0; int j=0; int l1 = mid-left+1; int l2 = right-mid; int s=left; //cout<<left<<" "<<mid<<" "<<right<<endl; while(1) { if(i==l1) { //cout<<left<<" "<<mid<<" "<<right<<endl; for(int k=j;k<l2;k++) { nums[s] = R[k]; s++; } return 0; } if(j==l2) { //cout<<left<<" "<<mid<<" "<<right<<endl; for(int k=i;k<l1;k++) { nums[s] = L[k]; s++; } return 0; } if(L[i]<=R[j]) { nums[s] = L[i]; i++; } else { //cout<<"here"<<endl; nums[s] = R[j]; result+=l1-i; j++; } s++; //cout<<left<<" "<<mid<<" "<<right<<endl; } } int mergeSort(int left,int right,vector<int> &nums) { if(left==right) { return 0; } int mid = (left+right)/2; mergeSort(left,mid,nums); mergeSort(mid+1,right,nums); merge(nums,left,mid,right); return 0; } public: int reversePairs(vector<int>& nums) { if(nums.empty()) return 0; mergeSort(0,nums.size()-1,nums); return result; } };
Merge sort plus one row result count.
52 [the first common node of two linked lists]
/** * Definition for singly-linked list. * struct ListNode { * int val; * ListNode *next; * ListNode(int x) : val(x), next(NULL) {} * }; */ class Solution { public: ListNode *getIntersectionNode(ListNode *headA, ListNode *headB) { unordered_map<ListNode*,int> map; auto cur = headA; while(cur!=NULL) { map[cur]++; cur = cur->next; } cur = headB; while(cur!=NULL) { if(map.find(cur)!=map.end()) { return cur; } cur = cur->next; } return NULL; } };
Hash map is a good thing.
53-I [find number I in sorted array]
class Solution { public: int search(vector<int>& nums, int target) { unordered_map<int,int> map; for(auto &it:nums) { map[it]++; } return map[target]; } };
53-II [missing numbers from 0 to n-1]
class Solution { public: int missingNumber(vector<int>& nums) { for(int i=0;i<nums.size();i++) { if(nums[i]!=i) { return i; } } return nums.size(); } };
54 [the k-th node of binary search tree]
/** * Definition for a binary tree node. * struct TreeNode { * int val; * TreeNode *left; * TreeNode *right; * TreeNode(int x) : val(x), left(NULL), right(NULL) {} * }; */ class Solution { vector<int> v; void recursion(TreeNode* root) { if(root==NULL) return; recursion(root->left); v.push_back(root->val); //cout<<root->val<<endl; recursion(root->right); } public: int kthLargest(TreeNode* root, int k) { recursion(root); return v[v.size()-k]; } };
55-I [depth of binary tree]
/** * Definition for a binary tree node. * struct TreeNode { * int val; * TreeNode *left; * TreeNode *right; * TreeNode(int x) : val(x), left(NULL), right(NULL) {} * }; */ class Solution { int depth; void recursion(TreeNode* root,int d) { if(root==NULL) { //cout<<" "<<d<<endl; depth = max(depth,d); return; } //cout<<d<<endl; //cout<<root->val<<endl; recursion(root->left,d+1); recursion(root->right,d+1); return; } public: int maxDepth(TreeNode* root) { depth = 0; int d = 0; recursion(root,d); return depth; } };
When the function is called, the passed in parameter is written as d + +, then the passed in parameter is still d.
55-II [balanced binary tree]
/** * Definition for a binary tree node. * struct TreeNode { * int val; * TreeNode *left; * TreeNode *right; * TreeNode(int x) : val(x), left(NULL), right(NULL) {} * }; */ class Solution { public: int height(TreeNode* root) { if (root == NULL) { return 0; } else { return max(height(root->left), height(root->right)) + 1; } } bool isBalanced(TreeNode* root) { if (root == NULL) { return true; } else { return abs(height(root->left) - height(root->right)) <= 1 && isBalanced(root->left) && isBalanced(root->right); } } };
The balanced binary tree can be recursively defined as: "the height difference of the current point is less than 1, and the left and right subtrees meet the balanced binary tree under this definition". Two recursive approaches.
56-I [number of occurrences of numbers in the array]
class Solution { public: vector<int> singleNumbers(vector<int>& nums) { int r = 0; for(auto &it:nums) { r = r^it; } vector<int> a; vector<int> b; int k = 0; while(1) { if(r>>k&1) break; k++; } for(auto &it:nums) { if(it>>k&1) a.push_back(it); else b.push_back(it); } vector<int> result; r = 0; for(auto &it:a) { r = r^it; } result.push_back(r); r = 0; for(auto &it:b) { r = r^it; } result.push_back(r); return result; } };
2 group XOR.
56-II [number of occurrences of numbers in array II]
class Solution { public: int singleNumber(vector<int>& nums) { unordered_map<int,int> map; for(auto &it:nums) { map[it]++; } for(auto &it:map) { if(it.second==1) { return it.first; } } return 0; } };
57 [and are two numbers of s]
class Solution { public: vector<int> twoSum(vector<int>& nums, int target) { int sz = nums.size(); int i = 0; int j = sz-1; int a,b; while(1) { if(i==j) break; a = nums[i]; b = nums[j]; if(a+b==target) break; if(a+b>target) { j--; continue; } if(a+b<target) { i++; continue; } } vector<int> result; result.push_back(a); result.push_back(b); return result; } };
Double finger acupuncture, wonderful.
57-II [sequence of continuous positive numbers with sum s]
class Solution { public: vector<vector<int>> findContinuousSequence(int target) { double sum; vector<vector<int>> result; vector<int> tmp; for(int i=1;i<target;i++) { //sum = i; for(int j=i+1;j<target;j++) { sum = (i+j)/2.0*(j-i+1); //sum = sum+j; if(sum>target) break; //if(abs(sum-target)<0.1) if(sum==target) { tmp.clear(); for(int k=i;k<=j;k++) { tmp.push_back(k); } result.push_back(tmp); } } } return result; } };
58-I [flip word order]
class Solution { public: string reverseWords(string s) { s+=" ";//Pretreatment int n = s.size(); vector<string> res; string tmp = ""; for(int i=0;i<n;i++) { if(s[i]==' ') { if(tmp.empty()) { continue; } res.push_back(tmp); tmp.clear(); } else { tmp.push_back(s[i]); } } reverse(res.begin(),res.end()); string result = ""; for(int i=0;i<res.size();i++) { result+=res[i]; if(i!=res.size()-1) { result+=" "; } } return result; } };
Find the "xxx empty" mode, and press in the temporary string when it is empty. When encountering a space, if the temporary string is empty, it means that the letter has not been pressed yet. It means that it is definitely not the space behind the letter. Just skip it directly.
It is best to fill in a space after the initial string.
58-II [rotate string left]
class Solution { public: string reverseLeftWords(string s, int n) { string result = ""; int sz = s.size(); for(int i=n;i<sz;i++) { result.push_back(s[i]); } for(int i=0;i<n;i++) { result.push_back(s[i]); } return result; }
};
59-I [maximum value of sliding window]
class Solution { public: vector<int> maxSlidingWindow(vector<int>& nums, int k) { if(nums.empty()) return {}; int n = nums.size(); priority_queue<pair<int, int>> q;//Use priority_queue constructs a large top heap, which is the default for (int i = 0; i < k; ++i) { q.emplace(nums[i], i); } vector<int> ans = {q.top().first};//Maximum value of the initial window for (int i = k; i < n; ++i) {//Start sliding q.emplace(nums[i], i); while (q.top().second <= i - k) {//The maximum value will pop out before the window. q.pop(); } ans.push_back(q.top().first); } return ans; } };
Ingenious application of large top pile. Judge whether the maximum value is in the window. If it is not in the window, use the idea of pop to remove it.
59-II [maximum value of queue]
class MaxQueue { int q[20000]; int begin = 0, end = 0; public: MaxQueue() { } int max_value() { int ans = -1; for (int i = begin; i != end; ++i) ans = max(ans, q[i]); return ans; } void push_back(int value) { q[end] = value; end++; } int pop_front() { if (begin == end) return -1; begin++; return q[begin-1]; } }; /** * Your MaxQueue object will be instantiated and called as such: * MaxQueue* obj = new MaxQueue(); * int param_1 = obj->max_value(); * obj->push_back(value); * int param_3 = obj->pop_front(); */
Use an array for violent construction.
60 [n dice points]
class Solution { public: vector<double> dicesProbability(int n) { vector<double> dp0(6,1.0/6); for(int i=2;i<=n;i++) { vector<double> dp(5*i+1,0); for(int j=1;j<=6;j++) { for(int k=0;k<dp0.size();k++) { dp[k+j-1] = dp[k+j-1]+1.0/6*dp0[k]; cout<<dp[k+j-1]<<endl; } } //cout<<dp[5*i]<<endl; dp0 = dp; } return dp0; } };
Dynamic programming replaces probability calculation.
61 [shunzi in playing cards]
class Solution { public: bool isStraight(vector<int>& nums) { sort(nums.begin(),nums.end()); int num_zero = 0; for(int i=0;i<nums.size();i++) { if(nums[i]==0) { num_zero++; } else { break; } } //cout<<nums.size()<<endl; //int s = 0; for(int i=0;i<nums.size()-1;i++) { if(nums[i]==0) continue; //cout<<nums[i+1]-nums[i]<<endl; if(nums[i+1]==nums[i]) return false; //sum+=nums[i+1]-nums[i]; } int s = nums[nums.size()-1] - nums[num_zero]; if(nums.size()-1<s) { return false; } return true; } };
62 [the last remaining number in the circle]
class Solution { int recursion(int n,int m) { if(n==1) { return 0; } int r = (recursion(n-1,m)+m)%n; return r; } public: int lastRemaining(int n, int m) { return recursion(n,m); } };
Dynamic programming, the transfer equation is f ( n , m ) = [ ( f ( n − 1 ) , m ) + m ] % n f(n,m) =[ (f(n-1),m)+m]\%n f(n,m)=[(f(n−1),m)+m]%n. It is very important to think clearly about this.
The timeout of the system is as follows:
class Solution { public: int lastRemaining(int n, int m) { vector<int> a(n); for(int i=0;i<n;i++) { a[i] = i; } int iter = -1; for(int i=0;i<n-1;i++) { int j = 0; while(1) { iter++; iter = iter%n; // cout<<iter<<" "<<j <<endl; if(a[iter]!=-1) { j++; } if(j==m) { //cout<<a[iter]<<endl; a[iter] = -1; break; } } } int result; for(auto &it:a) { if(it!=-1) { result = it; break; } } return result; } };
63 [maximum profit of shares]
class Solution { public: int maxProfit(vector<int>& prices) { int r = 0; for(int i=0;i<prices.size();i++) { for(int j=i+1;j<prices.size();j++) { r = max(r,prices[j]-prices[i]); } } return r; } };
Violence got rid of it.
64 [find 1 + 2 +... + n]
class Solution { public: int sumNums(int n) { n-1&&(n = n+sumNums(n-1)); return n; } };
If you can't see addition, subtraction, multiplication and division, judgment of loop conditions, etc., you can only use & & to find the recursive exit.
65 [addition without addition, subtraction, multiplication and division]
class Solution { public: int add(int a, int b) { int c; while(c!=0) { int n = a^b; c = (unsigned)(a & b)<<1; a = n; b = c; } return a; } };
Standard and carry, continuous cycle.
66 [build product array]
class Solution { public: vector<int> constructArr(vector<int>& a) { if(a.empty()) return {}; int sz = a.size(); vector<int> B(sz); vector<int> A(sz); int s = 1; int s1 = 1; for(int i=sz-1;i>=0;i--) { s*=a[i]; B[i] = s; s1 *= a[sz-1-i]; A[sz-1-i] = s1; } vector<int> result; result.push_back(B[1]); for(int i=1;i<sz-1;i++) { result.push_back(A[i-1]*B[i+1]); } result.push_back(A[sz-2]); return result; } };
The calculation is divided into two sections.
67 [convert string to integer]
class Solution { public: int strToInt(string str) { int flag=1; int tmp; long int result = 0; bool begin = false; for(int i=0;i<str.size();i++) { cout<<str[i]<<endl; if(str[i]==' ') { if(begin==false) { continue; } else{ break; } } else if(str[i]=='+') { if(begin==false) { flag = 1; begin = true; } else{ break; } } else if(str[i]=='-') { if(begin==false) { flag = -1; begin = true; } else{ break; } } else if(str[i]-'0'<=9&&str[i]-'0'>=0) { begin = true; tmp = str[i] - '0'; result = result*10+tmp; if(result<INT_MIN||result>INT_MAX) { if(flag>0) { return flag*INT_MAX; } else{ return INT_MIN; } } //cout<<flag<<endl; } else{ break; } } //cout<<str[str.size()-1]<<endl; return flag*result; } };
Strictly follow the ideas and steps and write slowly.
68-I [nearest common ancestor of binary search tree]
/** * Definition for a binary tree node. * struct TreeNode { * int val; * TreeNode *left; * TreeNode *right; * TreeNode(int x) : val(x), left(NULL), right(NULL) {} * }; */ class Solution { TreeNode* recursion(TreeNode* root,int a,int b) { int value = root->val; int m = min(a,b); int M = max(a,b); if(value>=m&&value<=M) { return root; } if(value<m) { return recursion(root->right,a,b); } else { return recursion(root->left,a,b); } } public: TreeNode* lowestCommonAncestor(TreeNode* root, TreeNode* p, TreeNode* q) { return recursion(root,p->val,q->val); } };
68-II [nearest common ancestor of binary tree]
/** * Definition for a binary tree node. * struct TreeNode { * int val; * TreeNode *left; * TreeNode *right; * TreeNode(int x) : val(x), left(NULL), right(NULL) {} * }; */ class Solution { public: TreeNode* res; bool recursion(TreeNode* root, TreeNode* p, TreeNode* q) {//Judge whether the number of nodes with root includes at least one node if (root == NULL) return false; bool lson = recursion(root->left, p, q); bool rson = recursion(root->right, p, q); if ((lson && rson) || ((root->val == p->val || root->val == q->val) && (lson || rson))) { res = root; } //Recursion while capturing common nodes return lson || rson || (root->val == p->val || root->val == q->val); } TreeNode* lowestCommonAncestor(TreeNode* root, TreeNode* p, TreeNode* q) { recursion(root, p, q); return res; } };
Supplementary questions
Queen N
class Solution { vector<vector<string>> result; vector<int> pos; int nG; int fresh( vector<vector<bool>> &M,int i,int j) { int sum = i+j; int sub = i-j; for(int i=0;i<nG;i++) { for(int j=0;j<nG;j++) { if(i+j==sum||i-j==sub) { M[i][j] = true; } } } return 0; } int pos2StrAndSave() { //vector<string> str(nG,"...."); string tmp(nG,'.'); vector<string> *str = new vector<string>(nG,tmp); for(int i=0;i<nG;i++) { (*str)[i][pos[i]] = 'Q'; } result.push_back(*str); return 0; } int recursion(int m,vector<bool> colOccu,vector<vector<bool>> M) { if(m>=nG) { pos2StrAndSave(); return 0; } for(int j=0;j<nG;j++) { if(colOccu[j]) continue; if(M[m][j]) continue; pos[m]= j; //cout<<m<<" "<<j<<endl; auto M_back = M; auto colOccu_back = colOccu; colOccu[j] = true; fresh(M,m,j); recursion(m+1,colOccu,M); M = M_back; colOccu = colOccu_back; } return 0; } public: vector<vector<string>> solveNQueens(int n) { vector<bool> colOccu(n,false); vector<vector<bool>> M(n,vector<bool>(n,false)); nG = n; pos.resize(n); recursion(0,colOccu,M); return result; } };
It can reduce a lot of work by traversing according to each row with only one row. Think about it before you start. Sharpen your knife without mistaking your firewood cutting skills.
If the result to be returned is to occupy the newly opened memory, you can't save the local variables of the function. In this way, the memory will disappear when the function returns. You should use new.
The array from new is a pointer. If you want to copy with its subscript index, you'd better add a *, such as (* str)[i][pos[i]] = 'Q';. Sometimes, unlike c, the first pointer represents an array.
For the problem of backtracking, if recursion is called in the for loop, remember to restore the changed value in each loop.
Quick sort
#include <iostream> #include<vector> #include<algorithm> //#include<bits/stdc++.h> using namespace std; //i starts from the leftmost element (pacesetter) and j starts from the rightmost element //j find elements smaller than std, i find elements larger than std, j go first (the pacesetter is on the left, the pacesetter is on the right, balanced) //When i==j, exchange the elements of std and j //The cycle is in 1 + 2 mode. There are two cycles in a cycle, one is the movement of the right model and the other is the movement of the left model //The code of other problems is written very clearly. Look at the code int swap(vector<int> &nums, int i, int j) { int tmp = nums[i]; nums[i] = nums[j]; nums[j] = tmp; return 0; } int qsort(vector<int> &nums,int left,int right) { if (left >= right) return 0;//If the left is greater than the right, it will return. Only write = =. It is not robust enough for two elements int std = nums[left]; int i = left;//On the left, it starts from the pacesetter position, so that there will be no bug s in the two elements int j = right; while (1) { if (i >= j) break; while (1)//Be sure to start on the right { if (j <= i || nums[j] < std)//When the left and right pointers meet or find a number smaller than the pacesetter, they exit { break; } j--; } while (1) { if (i >= j || nums[i] > std) { break; } i++; } if (i < j) { swap(nums, i, j); } } swap(nums, left, j);//Jump out of i + + and j -- and then exchange qsort(nums, left, j - 1); qsort(nums, j + 1, right); return 0; } int main() { vector<int> nums = { 1,3,1,4,5,2,0 }; qsort(nums,0,nums.size()-1); for (auto& it : nums) { cout << it << endl; } return 0; }
//i starts from the leftmost element (pacesetter) and j starts from the rightmost element
//j find elements smaller than std, i find elements larger than std, j go first (the pacesetter is on the left, the pacesetter is on the right, balanced)
//When i==j, exchange the elements of std and j
//The cycle is in 1 + 2 mode. There are two cycles in a cycle, one is the movement of the right model and the other is the movement of the left model
//In addition to comparing the left and right soldiers with the model soldiers, they also have to see if they meet. When they meet, they jump out of the circular model soldiers, and continue to look for them if they don't meet
//The code of other problems is written very clearly. Look at the code
486. Forecast winners
class Solution { public: bool PredictTheWinner(vector<int>& nums) { int n = nums.size(); vector<vector<int>> dp(n,vector<int>(n)); for(int i=0;i<n;i++) { dp[i][i] = nums[i]; } for(int i=n-2;i>=0;i--) { for(int j=i+1;j<n;j++) { dp[i][j] = max(nums[i]-dp[i+1][j],nums[j]-dp[i][j-1]); } } return dp[0][n-1]>=0; } };
The two-dimensional array dp[i][j] is used to represent the maximum score difference that the current decision-maker can obtain when facing the array from I position to j position. The maximum score difference means that one's score minus others' score, and the decision-maker makes it as large as possible.