剑指offer刷题day-1 (13道题)
本篇博客是自己的刷题笔记,也不分享什么思路啥的,直接放的自己写的通过的答案,就是记录一下,也起一个督促的作用!
知识点梳理(重点掌握 二叉树的重建,位运算)
1.类似于二分从右上角开始找,复杂度o(n2)—>0(n+m) 就是o(n)级别的
2.语法题,python里的replace函数
3.vector(ans.rbegin(),ans.rend()) 返回一个反转数组
4.重点:递归调用+hash表存储位置
5.两个栈,自己定义一个交换函数
6.将相等的数字清除掉,用二分来写降低时间复杂度
7.8.9.10.类似于斐波那契数列
11.位运算,右移与运算判断最右边的数字是否为1
12.细心的题,简单
13.是否要求奇数和偶数保持和原来的位置不变,做法也不一样
具体代码:
//1.二维数组中的查找
//类似于二分的做法,从右上角开始判断,每次减去1行或者1列,将o(n2)的复杂度降为m+n,就是o(n)
class Solution {
public:
bool searchArray(vector<vector<int>> array, int target) {
if(array.size()==0 || array[0].size()==0) return false;
int m=array.size()-1,n=array[0].size()-1;
while(i<m && j>0){
if(array[i][j]<target) i++;
else if(array[i][j]>target) j--;
else return true;
}
return array[i][j]==target;
}
};
//2.替换空格 (语法题)
//python 直接用replace就可以
class Solution(object):
def replaceSpaces(self, s):
"""
:type s: str
:rtype: str
"""
if len(s)==0:
return s
else:
return s.replace(" ","%20")
//c++就是字符串的拼接,扫一遍列表
class Solution {
public:
string replaceSpaces(string &str) {
string ans;
int n=str.size();
if(n==0) return str;
for(int i=0;i<n;i++){
if(str[i]==' ') ans+="%20";
else ans+=str[i];
}
return ans;
}
};
//3.从尾到头打印链表
//直接遍历完打印,然后将vector逆序输出即可
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode(int x) : val(x), next(NULL) {}
* };
*/
class Solution {
public:
vector<int> printListReversingly(ListNode* head) {
auto cur=head;
vector<int> ans;
while(cur){
ans.push_back(cur->val);
cur=cur->next;
}
return vector<int>(ans.rbegin(),ans.rend());
}
};
//4.重建二叉树
//递归的做法
//前序遍历:根左右
//中序遍历:左根右
//后序遍历:左右跟 每一层都递归的走一遍
/**
* 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:
unordered_map<int,int> position;
vector<int> preorder,inorder;
TreeNode* buildTree(vector<int>& _preorder, vector<int>& _inorder) {
preorder=_preorder,inorder=_inorder;
return rebuild_tree(preorder,inorder,0,preorder.size()-1,0,inorder.size()-1);
}
TreeNode* rebuild_tree(vector<int> preorder,vector<int> inorder,int pl,int pr, int il,int ir){
if(pl>pr) return NULL;
for (int i=0;i<inorder.size();i++){
position[inorder[i]]=i;
}
int k=position[preorder[pl]]-il; //找出每次遍历的左右子树的长度,保证每次递归时候的个数
TreeNode* root=new TreeNode(preorder[pl]);
root->left=rebuild_tree(preorder,inorder,pl+1,pl+k,il,il+k-1);
root->right=rebuild_tree(preorder,inorder,pl+k+1,pr,il+k+1,ir);
return root;
}
};
//5.用两个栈实现队列
class MyQueue {
public:
//定义两个栈
stack<int> stk,cache;
/** Initialize your data structure here. */
MyQueue() {
}
/** Push element x to the back of queue. */
void push(int x) {
stk.push(x)
}
void swap_stk(stack<int> &a,stack<int> &b){
while(a.size()){
b.push(a.top());
a.pop();
}
}
/** Removes the element from in front of queue and returns that element. */
int pop() {
swap_stk(stk,cache);
int res=cache.top();
cache.pop();
swap_stk(cache,stk);
return res;
}
/** Get the front element. */
int peek() {
swap_stk(stk,cache);
int res = cache.top();
swap_stk(cache,stk);
return res;
}
/** Returns whether the queue is empty. */
bool empty() {
return stk.empty();
}
};
/**
* Your MyQueue object will be instantiated and called as such:
* MyQueue obj = MyQueue();
* obj.push(x);
* int param_2 = obj.pop();
* int param_3 = obj.peek();
* bool param_4 = obj.empty();
*/
//6.旋转数组的最小数字
//因为有重复的元素,正常的话扫一遍数组肯定是可以通过的
class Solution {
public:
int findMin(vector<int>& nums) {
int n=nums.size();
if(n==0) return -1;
for (int i=0;i<n-1;i++){
if(nums[i]>nums[i+1]){
int a=i+1;
return nums[a];
break;
}
}
return nums[0];
}
};
//优化的版本
class Solution {
public:
int findMin(vector<int>& nums) {
int n=nu
}
};
//7.斐波那契数列
//语法题:
class Solution {
public:
int Fibonacci(int n) {
int a=0,b=1;
while(n--){
int c=a+b;
a=b;
b=c;
}
return a;
}
};
//递归的做法
class Solution {
public:
int Fibonacci(int n) {
if(n==0) return 0;
if(n==1 || n==2) return 1;
return Fibonacci(n-1)+Fibonacci(n-2);
}
};
//8.走台阶
//每次走一级或者两级 递归的做法并不好,但剑指offer中或者其他刷题中,递归的数据范围都比较小,所以也pass
//f[i]可以从上一级楼梯走过来,也可以从上两级楼梯走过来 f[i-1] and f[i-2]
//f[i]有几种走法 f[i]=f[i-1]+f[i-2]; 简单的递归,边界情况为 f[1]=1 f[2]=2 ,所以f[3]=f[1]+f[2]=3
// 1,2 2,1, 1,1,1 三种情况
class Solution {
public:
int jumpFloor(int number) {
if(number==1) return 1;
if(number==2) return 2;
return jumpFloor(number-1)+jumpFloor(number-2);
}
};
//9.变态跳台阶,一次可以跳3,4,5或者n阶台阶
//可以跳i个台阶//cn0+cn1+cn2+....+cnn/2=2的n-1次方
class Solution {
public:
int jumpFloorII(int number) {
return pow(2,number-1);
}
};
//常规的递归来考虑
//思路同上题:f[n]=f[n-1]+f[n-2]+f[n-3]+f[n-4]+...+f[0],
//而这里 :f[n-1]=f[n-2]+f[n-3]+f[n-4]+...+f[0];
//所以将剩下的一坨用f[n-1]来代替,所以f[n]=2*f[n-1]
class Solution {
public:
int jumpFloorII(int number) {
if(number==0 || number==1) return 1;
else
return 2*jumpFloorII(number-1);
}
};
//10.矩形覆盖
//我们可以用2*1的小矩形横着或者竖着去覆盖更大的矩形。请问用n个2*1的小矩形无重叠地覆盖一个2*n的大矩形,总共有多少种方法?
//斐波那契数列
class Solution {
public:
int rectCover(int number) {
if (number < 1) {
return 0;
}
else if (number == 1 || number == 2) {
return number;
}
else {
return rectCover(number-1) + rectCover(number-2);
}
}
};
//11.二进制中1的个数
//位运算 与上1就可以判断末尾数字是否为1
class Solution {
public:
int NumberOf1(int n) {
int res=0;
unsigned int un=n;
while(un){
res+=un&1;
un>>=1;
}
return res;
}
};
//12.数值的整数次方
//就是直接累积乘就可以~
class Solution {
public:
double Power(double base, int exponent) {
if(exponent==0) return 1;
if(base==0) return 0;
int index=1;
if(exponent<0) exponent=-exponent,index=-1;
double res=1;
while(exponent--){
res=res*base;
}
if(index==-1) res=1/res;
return res;
}
};
//13.调整次序使得左边是奇数,右边是偶数
class Solution {
public:
void reOrderArray(vector<int> &array) {
int N=array.size();
if(N==0) return ;
vector<int> ji,ou;
for(int i=0;i<N;i++){
if(array[i]%2==1) ji.push_back(array[i]);
else ou.push_back(array[i]);
}
// cout<<ou[0];
for(int i=0;i<ji.size();i++){
array[i]=ji[i];
}
for(int j=ji.size();j<N;j++){
array[j]=ou[j-ji.size()];
}
}
};
明天剑指offe刷题day2继续!秋招加油!