文章目录
04. 二维数组中的查找
最初思路,矩阵二分。如果(mh,ml)的值大于target,那么(mh,ml)为左上角,(bh,bl)为右下角的矩阵内肯定没有target。小于target的判断方式同理。这个思路刷出来的最好用时16 ms(97.00%),内存12.6 MB(83.88%)(全靠刷)。复杂度是
class Solution {
public:
bool findNumberIn2DArray(vector<vector<int>>& matrix, int target) {
int h = matrix.size();
if(h == 0) return false;
int l = matrix[0].size();
return binary2(matrix, 0, h-1, 0, l-1, target);
}
bool binary2(vector<vector<int>>& matrix, int sh, int bh, int sl, int bl, int target){
if(sh > bh || sl > bl) return false;
if(target < matrix[sh][sl] || target > matrix[bh][bl]) return false;
int mh = (sh + bh) >> 1;
int ml = (sl + bl) >> 1;
if(matrix[mh][ml] == target) return true;
if(matrix[mh][ml] > target){
return binary2(matrix, sh, mh-1, sl, ml-1, target) |
binary2(matrix, mh, bh, sl, ml-1, target) |
binary2(matrix, sh, mh-1, ml, bl, target);
}
else if(matrix[mh][ml] < target){
return binary2(matrix, mh+1, bh, ml+1, bl, target) |
binary2(matrix, mh+1, bh, sl, ml, target) |
binary2(matrix, sh, mh, ml+1, bl, target);
}
return false;
}
};
感觉题解思路更好,从右上角开始走,正左边的数都小于自身,正下方的数都大于自身。因此可以二分的走。复杂度是 O ( m a x ( n , m ) ) O(max(n,m)) O(max(n,m))
class Solution {
public:
bool findNumberIn2DArray(vector<vector<int>>& matrix, int target) {
int h = matrix.size();
if(h == 0) return false;
int l = matrix[0].size() - 1;
int ch = 0;
while(ch < h && l >= 0){
if(matrix[ch][l] > target){
l--;
}
else if(matrix[ch][l] < target){
ch++;
}
else{
return true;
}
}
return false;
}
};
07. 重建二叉树
已知先序中序求二叉树。用时32 ms(26.45%),内存24.4 MB(85.28%)
/**
* 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* buildTree(vector<int>& preorder, vector<int>& inorder) {
return build(preorder, inorder, 0, preorder.size()-1, 0, inorder.size()-1);
}
TreeNode* build(vector<int>& preorder, vector<int>& inorder, int pl, int pr, int il, int ir){
if(pl > pr || il > ir) return NULL;
//先序 pl位置是根节点
//中序 先左子树 然后根节点 然后右子树
TreeNode* curr = new TreeNode();
int rt = preorder[pl];
curr->val = rt;
int rt_sit = il;
while(inorder[rt_sit] != rt) rt_sit++;
//中序 [il, rt_sit-1] [rt_sit] [rt_sit+1, ir]
int lson = rt_sit - il;
int rson = ir - rt_sit;
//先序 [pl] [pl+1, pl+lson] [pl+lson+1, pr]
curr->left = build(preorder, inorder, pl+1, pl+lson, il, rt_sit-1);
curr->right = build(preorder, inorder, pl+lson+1, pr, rt_sit+1, ir);
return curr;
}
};
对时间的改进:牺牲内存,用unordered_map<int, int> mp;
来记录inorder中每个数字的下标,这样就不需要枚举查询rt_sit了,直接int rt_sit = mp[preorder[pl]];
12. 矩阵中的路径
暴力dfs
const int mx = 8;
class Solution {
public:
int op[4][2] = {{0,1}, {0,-1}, {1,0}, {-1,0}};
int len;
int H, L;
bool vis[mx][mx];
bool exist(vector<vector<char>>& board, string word) {
H = board.size(), L = board[0].size();
len = word.length();
for(int h = 0; h < H; h++){
for(int l = 0; l < L; l++){
if(fun(board, h, l, 0, word)) return true;
}
}
return false;
}
bool fun(vector<vector<char>>& board, int h, int l, int id, string word){
if(h < 0 || h >= H || l < 0 || l >= L) return false;
if(vis[h][l] || board[h][l] != word[id]) return false;
if(id == len-1)return true;
vis[h][l] = true;
bool ok = false;
for(int i = 0; i < 4; i++){
ok = fun(board, h+op[i][0], l+op[i][1], id+1, word);
if(ok) break;
}
vis[h][l] = false;
return ok;
}
};
14- I. 剪绳子
直觉告诉我凑3,如果余1就取一个3凑2x2=4。
题解:算术几何均值不等式 求导 得最佳割分为e。近似整数3。
typedef long long ll;
class Solution {
public:
int cuttingRope(int n) {
if(n < 5){
if(n == 1) return 0;
if(n == 2) return 1;
if(n == 3) return 2;
if(n == 4) return 4;
}
ll ans = 1;
while(n >= 5){
ans = ans * 3LL;
n -= 3;
}
if(n == 4) ans *= 4;
if(n <= 3) ans *= n;
return ans;
}
};
14- II. 剪绳子 II
同上,补快速幂
typedef long long ll;
const ll mod = 1e9 + 7;
class Solution {
public:
ll ksm(ll a, ll b){
ll ans = 1;
while(b){
if(b&1) ans = (ans * a) % mod;
a = (a * a) % mod;
b >>= 1;
}
return ans;
}
int cuttingRope(int n) {
if(n <= 3) return n - 1;
if(n % 3 == 0) return ksm(3LL, n/3);
if(n % 3 == 2) return ksm(3LL, n/3) * 2LL % mod;
// n % 3 == 1
return ksm(3LL, n/3 - 1) * 4LL % mod;
}
};
16. 数值的整数次方
快速幂,注意int范围是[-2147483647, 2147483648]。因此取负后可能超出int。
class Solution {
public:
double ksm(double a, long long b){
double ans = 1;
while(b){
if(b&1) ans = ans * a;
a = a * a;
b >>= 1;
}
return ans;
}
double myPow(double x, int n) {
if(n == 0) return 1.0;
if(n < 0) return ksm(1.0/x, (-1LL) * n);
return ksm(x, n);
}
};
20. 表示数值的字符串
大模拟
class Solution {
public:
bool allNumber(string s, int l, int r){
if(l > r) return false;//empty
for(int i = l; i <= r; i++)
if(s[i] < '0' || s[i] > '9') return false;
return true;
}
int findCharOnly(string s, char c1, char c2, int l, int r){
int id = -1;
for(int i = l; i <= r; i++){
if(s[i] == c1 || s[i] == c2){
if(id != -1) return -2;//false
id = i;
}
}
return id;
}
bool isXiaoshu(string s, int l, int r){
if(s[l] == '-' || s[l] == '+') l++;
int dot = findCharOnly(s, '.', '.', l, r);
if(dot == -2) return false;//多个小数点
if(dot == -1) return allNumber(s, l, r);//没有小数点
bool b1 = (dot == l? true: allNumber(s, l, dot-1));
bool b2 = (dot == r? true: allNumber(s, dot+1, r));
//或者只有一个. 这样是不对的
if(dot == l && dot == r) return false;
return b1 && b2;
}
bool isZhengshu(string s, int l, int r){
if(s[l] == '-' || s[l] == '+') l++;
return allNumber(s, l, r);
}
bool isNumber(string s) {
if(s.length() == 0) return false;
int l = 0, r = s.length()-1;
while(l <= r && s[l] == ' ') l++;
while(l <= r && s[r] == ' ') r--;
if(l > r) return false;
int e = findCharOnly(s, 'e', 'E', l, r);
if(e == -2) return false;
if(e == -1) return isXiaoshu(s, l, r) || isZhengshu(s, l, r);
//存在e
bool b1 = isXiaoshu(s, l, e-1) || isZhengshu(s, l, e-1);
bool b2 = isZhengshu(s, e+1, r);
return b1 && b2;
}
};
26. 树的子结构
暴力
/**
* 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 same(TreeNode* A, TreeNode* B){
if(A == NULL && B == NULL) return true;
if(A != NULL && B == NULL) return true;
if(A == NULL && B != NULL) return false;
if(A->val != B->val) return false;
return same(A->left, B->left) && same(A->right, B->right);
}
bool hasB(TreeNode *A, TreeNode *B){
if(A == NULL) return false;
if(same(A, B)) return true;
return hasB(A->left, B) || hasB(A->right, B);
}
bool isSubStructure(TreeNode* A, TreeNode* B) {
if(A == NULL || B == NULL) return false;
return hasB(A, B);
}
};
31. 栈的压入、弹出序列
验证栈的压入、弹出序列。直接模拟压入过程,如果当前栈顶是弹出序列当前值,就执行弹出。
数组实现栈占用的内存会更小
class Solution {
public:
bool validateStackSequences(vector<int>& pushed, vector<int>& popped) {
int num = pushed.size(), j = 0;
int sta[num+1], head = 0;
for(int i = 0; i < num; i++){
sta[++head] = pushed[i];
while(head >= 1 && sta[head] == popped[j]){
head--;
j++;
}
}
return j == num;
}
};
32 - I. 从上到下打印二叉树
bfs
class Solution {
public:
vector<int> levelOrder(TreeNode* root) {
vector<int>ans;
queue<TreeNode*>q;
q.push(root);
while(!q.empty()){
TreeNode *curr = q.front();
q.pop();
if(curr == NULL) continue;
ans.push_back(curr->val);
q.push(curr->left);
q.push(curr->right);
}
return ans;
}
};