剑指offer算法笔记——数组
题目
JZ1-二维数组中的查找
对每一行进行二分查找,复杂度nlogn,再次基础上,基于对前一行的二分查找,可以确定上一行二分查找确定的位置,其右下部分都不可能出现所需数字,当然,有更加优化的方法logm*logn
static const auto io_sync_off = []()
{
// turn off sync
std::ios::sync_with_stdio(false);
// untie in/out streams
std::cin.tie(nullptr);
return nullptr;
}();
class Solution {
public:
int min_j;
int min(int a,int b)
{
return a<=b?a:b;
}
bool tow_find(int row,int l,int r,int target,vector<vector<int> > array)
{
int mid;
while(l<=r)
{
mid = (l+r)/2;
if(array[row][mid]<target)
{
l = mid+1;
}
else if(array[row][mid]>target)
{
r = mid-1;
}
else
return true;
}
min_j = l;//确保这个数大于我们查找的树,右下角舍弃
return false;
}
bool Find(int target, vector<vector<int> > array) {
bool ans = false;
min_j = array[0].size();
for(int i=0;i<array.size();i++)
{
if(tow_find(i,0,min(array[i].size()-1,min_j),target,array))
{
return true;
}
}
return false;
}
};
JZ4-重建二叉树
给定先序和中序遍历,构造一棵二叉树,dfs直接递归写,好久不写了,遇到个坑,就是传数组时,直接把pre和vin的size传了进去,忘记-1,导致在坑里跳了很久。
/**
* Definition for binary tree
* struct TreeNode {
* int val;
* TreeNode *left;
* TreeNode *right;
* TreeNode(int x) : val(x), left(NULL), right(NULL) {}
* };
*/
class Solution {
public:
TreeNode* dfs(int s1,int e1,int s2,int e2,vector<int> pre,vector<int> vin)
{
int index;
//cout<<s1<<" "<<e1<<" "<<s2<<" "<<e2<<endl;
TreeNode *cur = new TreeNode(pre[s1]);
cur->val = pre[s1];
for(int i=s2;i<=e2;i++)
{
if(vin[i]==pre[s1])
{
index = i;
break;
}
}
int dd = index - s2;
if(index == s2)
{
cur->left = NULL;
}
else
{
cur->left = dfs(s1+1,s1+dd,s2,index-1,pre,vin);
}
if(index == e2)
{
cur->right = NULL;
}
else
{
cur->right = dfs(s1+dd+1,e1,index+1,e2,pre,vin);
}
return cur;
}
TreeNode* reConstructBinaryTree(vector<int> pre,vector<int> vin) {
TreeNode *root = new TreeNode(pre[0]);
int index = 0;
int m = vin.size();
for(int i=0;i<m;i++)
{
if(vin[i] == pre[0])
{
index = i;
break;
}
}
if(index == 0)
{
root->left = NULL;
}
else
root->left = dfs(1,index,0,index-1,pre,vin);
if(index == m-1)
{
root->right = NULL;
}
else
root->right = dfs(1+index,pre.size()-1,index+1,vin.size()-1,pre,vin);//pre和vin的size不能忘记-1!
return root;
}
};
自己太菜,学习到简化后的代码:
/**
* Definition for binary tree
* struct TreeNode {
* int val;
* TreeNode *left;
* TreeNode *right;
* TreeNode(int x) : val(x), left(NULL), right(NULL) {}
* };
* 人写的代码
*/
class Solution {
public:
TreeNode* dfs(int s1,int e1,int s2,int e2,vector<int> pre,vector<int> vin)
{
int index;
if(s1>e1)
return nullptr;
TreeNode *cur = new TreeNode(pre[s1]);
cur->val = pre[s1];
for(int i=s2;i<=e2;i++)
{
if(vin[i]==pre[s1])
{
index = i;
break;
}
}
int dd = index - s2;
cur->left = dfs(s1+1,s1+dd,s2,index-1,pre,vin);
cur->right = dfs(s1+dd+1,e1,index+1,e2,pre,vin);
return cur;
}
TreeNode* reConstructBinaryTree(vector<int> pre,vector<int> vin) {
return dfs(0,pre.size()-1,0,vin.size()-1,pre,vin);
}
};
JZ7-斐波那契数列
class Solution {
public:
int Fibonacci(int n) {
int a[50];
a[0] = 0;
a[1] = 1;
for(int i=2;i<=39;i++)
a[i] = a[i-1]+a[i-2];
return a[n];
}
};
JZ13-调整数组顺序使奇数位于偶数前面
class Solution {
public:
/**
* 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
*
*
* @param array int整型vector
* @return int整型vector
*/
vector<int> reOrderArray(vector<int>& array) {
// write code here
int flag = 0;
for(int i=0;i<array.size();i++)
{
if(array[i]&1)
{
int m = i;
int temp = array[m];
while(m>flag)
{
array[m] = array[m-1];
m--;
}
array[flag] = temp;
flag++;
}
}
return array;
}
};
JZ19- 顺时针打印矩阵
把矩阵当成一个图去跑就行了,跑的规则是右下左上,每当一个方法遇到边界的时候就换下一个方法,设置四个方向的边界值,边界值的变化有四种情况:
1)如果往右跑的话,到边界那么矩阵的上边界就+1。
2)如果往下跑的话,到边界那么矩阵的右边界就-1。
3)如果往左跑的话,到边界那么矩阵的下边界就-1。
4)如果往上跑的话,到边界那么矩阵的左边界就+1。
class Solution {
public:
int dir[4][2]={0,1,1,0,0,-1,-1,0};
//int vis[1000][1000]={0};
vector<int> printMatrix(vector<vector<int> > matrix) {
vector<int> p;
int n = matrix.size();
int m = matrix[0].size();
//cout<<n<<" "<<m<<endl;
int i=0,j=0;
int flag = 0;
int sum = n*m;
int x_l = 0,x_r = n;
int y_l = 0,y_r = m;
for(int k = 0;k<sum;k++)
{
p.push_back(matrix[i][j]);
int x = i+dir[flag][0];
int y = j+dir[flag][1];
if(x<x_l||x==x_r||y<y_l||y==y_r)
{
if(flag==0){x_l++;}
else if(flag==1){y_r--;}
else if(flag==2){x_r--;}
else if(flag==3){y_l++;}
flag = (flag+1)%4;
}
i += dir[flag][0];
j += dir[flag][1];
}
return p;
}
};
JZ28-数组中出现次数超过一半的数字
看到一个有趣的想法,空间复杂度比自己想的低很多
自己代码:
class Solution {
public:
int MoreThanHalfNum_Solution(vector<int> numbers) {
int half = numbers.size()/2+1;
int ans = 0;
int sum = numbers.size();
map <int,int>vis;
for(int i=0;i<sum;i++)
{
vis[numbers[i]]++;
if(vis[numbers[i]]==half)
{
ans = numbers[i];
break;
}
}
return ans;
}
};
更好的思路:如果当前数据存在某个数的个数超过一半,那么根据以下规则这个数一定会是最后的数。
1)每当遇到一个数,将其数量设为1。
2)如果遇到的下个数不是同一个数,那么就进行消掉,将count设为0。如果遇到的数是一个数,那么count++。
3)如果count为0,那么给遇到的这个数count为1。
4)最最后留下的数进行O(n)的遍历,如果超过一半,那么答案就是他,如果没超过一半,那么答案为0。,
class Solution {
public:
int MoreThanHalfNum_Solution(vector<int> numbers) {
int count = 0;
int ans;
for(int n:numbers)
{
if(count==0)
{
ans = n;
count = 1;
}
else if(n!=ans)
{
count--;
}
else if(n == ans)
{
count++;
}
}
count = 0;
for(int i=0;i<numbers.size();i++)
{
if(numbers[i]==ans)
{
count++;
}
}
if(count <=numbers.size()/2)
{
ans = 0;
}
return ans;
}
};
JZ37-数字在排序数组中出现的次数
class Solution {
public:
int tow_find(vector<int> data,int k)
{
int l = 0,r = data.size()-1;
int mid = (l+r)/2;
int ans = data.size()-1;
while(l<=r)
{
if(data[mid]<k)
{
l = mid+1;
}
else if(data[mid]>=k)
{
ans = mid;
r = mid-1;
}
mid =(l+r)/2;
}
return ans;
}
int GetNumberOfK(vector<int> data ,int k) {
int pos = tow_find(data,k);
//cout<<pos<<endl;
int ans = 0;
for(int i=pos;i<data.size();i++)
{
if(data[i]!=k)
{
break;
}
ans++;
}
return ans;
}
};
JZ42-和为S的两个数字
class Solution {
public:
vector<int> FindNumbersWithSum(vector<int> array,int sum) {
map<int,int>mmp;
for(int i=0;i<array.size();i++)
{
mmp[array[i]] = 1;
}
vector<int> ans;
int mul_ans=0x3f3f3f;
for(int i = 0;i<array.size();i++)
{
if(mmp[sum-array[i]]==1)
{
int tem_ans = array[i]*(sum-array[i]);
if(tem_ans < mul_ans)
{
mul_ans = tem_ans;
ans.clear();
ans.push_back(array[i]);
ans.push_back(sum-array[i]);
}
}
}
return ans;
}
};
JZ50-数组中重复的数字
class Solution {
public:
/**
* 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
*
*
* @param numbers int整型vector
* @return int整型
*/
int duplicate(vector<int>& numbers) {
// write code here
map<int,int> mmp;
for(int i = 0;i<numbers.size();i++)
{
if(mmp[numbers[i]]==1)
{
return numbers[i];
}
mmp[numbers[i]] = 1;
}
return -1;
}
};