剑指offer算法笔记——数组

题目

JZ1-二维数组中的查找

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-重建二叉树

PZ4
给定先序和中序遍历,构造一棵二叉树,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;
    }
};
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值