剑指offer(刷题61-65)--c++,Python版本

目录

第61题:

给定一棵二叉搜索树,请找出其中的第k小的结点。例如, (5,3,7,2,4,6,8) 中,按结点数值大小顺序第三小结点的值为4。

解题思路:

  • 由于是二叉搜索树,其节点存放的值是有一定的规律的,所以我们可以使用一个数组存放二叉搜索树的中序遍历结果,然后直接将数字的第K个结果给出即可。时间复杂度为O(N),空间复杂度也为O(N)。

代码实现:

c++
class Solution {
public:
    int index = 0;
    TreeNode* KthNode(TreeNode* pRoot, int k)
    {
        if(pRoot != NULL){
            TreeNode* node = KthNode(pRoot->left , k);
            if(node != NULL) return node;
            index ++;
            if(index == k) return pRoot;
            node = KthNode(pRoot->right , k);
            if(node != NULL) return node;
        }
        return NULL;
    } 
};

运行时间:4ms

占用内存:608k

class Solution {
public:

    TreeNode* KthNode(TreeNode* pRoot, unsigned int k)
    {
        if(pRoot==NULL||k<=0) return NULL;
        vector<TreeNode*> vec;
        Inorder(pRoot,vec);
        if(k>vec.size())
            return NULL;
        return vec[k-1];
    }
    //中序遍历,将节点依次压入vector中
    void Inorder(TreeNode* pRoot,vector<TreeNode*>& vec)
    {
        if(pRoot==NULL) return;
        Inorder(pRoot->left,vec);
        vec.push_back(pRoot);
        Inorder(pRoot->right,vec);
    } 
};
python
# -*- coding:utf-8 -*-

第62题:

如何得到一个数据流中的中位数?如果从数据流中读出奇数个数值,那么中位数就是所有数值排序之后位于中间的数值。如果从数据流中读出偶数个数值,那么中位数就是所有数值排序之后中间两个数的平均值。我们使用Insert()方法读取数据流,使用GetMedian()方法获取当前读取数据的中位数。

解题思路:

/**
* 插入有两种思路:
* 1:直接插入大堆中,之后若两堆尺寸之差大于1(也就是2),则从大堆中弹出堆顶元素并插入到小堆中
* 若两队之差不大于1,则直接插入大堆中即可。
* 2:奇数个数插入到大堆中,偶数个数插入到小堆中,
* 但是 可能会出现当前待插入的数比小堆堆顶元素大,此时需要将元素先插入到小堆,然后将小堆堆顶元素弹出并插入到大堆中
* 对于偶数时插入小堆的情况,一样的道理。why?
* 因为要保证最大堆的元素要比最小堆的元素都要小。
* @param num
*/

代码实现:

c++
class Solution {
public:

    priority_queue<int, vector<int>, less<int> > p;  //小堆
    priority_queue<int, vector<int>, greater<int> > q; //大堆
    void Insert(int num)
    {
        if(p.empty() || num <= p.top()) p.push(num);
        else q.push(num);
        if(p.size() == q.size() + 2) q.push(p.top()), p.pop();
        if(p.size() + 1 == q.size()) p.push(q.top()), q.pop();
    }

    double GetMedian()
    { 
        return p.size() == q.size() ? (p.top() + q.top()) / 2.0 : p.top();
    }

};

运行时间:6ms

占用内存:484k

python
# -*- coding:utf-8 -*-

第63题:

给定一个数组和滑动窗口的大小,找出所有滑动窗口里数值的最大值。例如,如果输入数组{2,3,4,2,6,2,5,1}及滑动窗口的大小3,那么一共存在6个滑动窗口,他们的最大值分别为{4,4,6,6,6,5}; 针对数组{2,3,4,2,6,2,5,1}的滑动窗口有以下6个: {[2,3,4],2,6,2,5,1}, {2,[3,4,2],6,2,5,1}, {2,3,[4,2,6],2,5,1}, {2,3,4,[2,6,2],5,1}, {2,3,4,2,[6,2,5],1}, {2,3,4,2,6,[2,5,1]}。

解题思路:

  • 暴力解法:直接使用滑动窗的原理,得出每个窗口的数据,然后给出最大值即可。时间复杂度为O(N^2).

代码实现:

c++

python
# -*- coding:utf-8 -*-
class Solution:
    def maxInWindows(self, num, size):
        # write code here
        resList = []
        sampleNum = (len(num)-size + 1)
        if sampleNum <= 0 or size <=0:
            return resList
        for i in range(sampleNum):
            resList.append(max(num[i:i+size]))
        return resList

运行时间:31ms

占用内存:5728k

第64题:

请设计一个函数,用来判断在一个矩阵中是否存在一条包含某字符串所有字符的路径。路径可以从矩阵中的任意一个格子开始,每一步可以在矩阵中向左,向右,向上,向下移动一个格子。如果一条路径经过了矩阵中的某一个格子,则之后不能再次进入这个格子。 例如 a b c e s f c s a d e e 这样的3 X 4 矩阵中包含一条字符串"bcced"的路径,但是矩阵中不包含"abcb"路径,因为字符串的第一个字符b占据了矩阵中的第一行第二个格子之后,路径不能再次进入该格子。

解题思路:

代码实现:

c++
class Solution {
    bool hasPathRecu(char* matrix, int rows, int cols, int row, int col, char *str, int length, vector<bool> used)
    {
        if(length==strlen(str))
            return true;
        if(row<0||row>=rows||col<0||col>=cols)
            return false;
        int index = col + row*cols;
        bool result = false;
        if( !used[index] && matrix[index]==str[length]){
            used[index] = true;
            result = hasPathRecu(matrix, rows, cols, row-1, col, str, length+1, used)|| hasPathRecu(matrix, rows, cols, row+1, col, str, length+1, used)
                ||hasPathRecu(matrix, rows, cols, row, col+1, str, length+1, used)||hasPathRecu(matrix, rows, cols, row, col-1, str, length+1, used);
            used[index] = false;
        }
        if(result)
            return true;
        return false;
    }
public:
    bool hasPath(char* matrix, int rows, int cols, char* str)
    {
        vector<bool> used(strlen(matrix),false);
        if(str==NULL) return true;
        for(int i=0;i<rows;i++){
            for(int j=0;j<cols;j++){
                if(hasPathRecu(matrix, rows, cols, i, j, str, 0, used))
                    return true;
            }
        }
        return false;
     
    }
};

运行时间:5ms

占用内存:364k

python
# -*- coding:utf-8 -*-

第65题:

地上有一个m行和n列的方格。一个机器人从坐标0,0的格子开始移动,每一次只能向左,右,上,下四个方向移动一格,但是不能进入行坐标和列坐标的数位之和大于k的格子。 例如,当k为18时,机器人能够进入方格(35,37),因为3+5+3+7 = 18。但是,它不能进入方格(35,38),因为3+5+3+8 = 19。请问该机器人能够达到多少个格子?

解题思路:

代码实现:

c++
回溯法
class Solution {
    bool hasPathRecu(char* matrix, int rows, int cols, int row, int col, char *str, int length, vector<bool> used)
    {
        if(length==strlen(str))
            return true;
        if(row<0||row>=rows||col<0||col>=cols)
            return false;
        int index = col + row*cols;
        bool result = false;
        if( !used[index] && matrix[index]==str[length]){
            used[index] = true;
            result = hasPathRecu(matrix, rows, cols, row-1, col, str, length+1, used)|| hasPathRecu(matrix, rows, cols, row+1, col, str, length+1, used)
                ||hasPathRecu(matrix, rows, cols, row, col+1, str, length+1, used)||hasPathRecu(matrix, rows, cols, row, col-1, str, length+1, used);
            used[index] = false;
        }
        if(result)
            return true;
        return false;
    }
public:
    bool hasPath(char* matrix, int rows, int cols, char* str)
    {
        vector<bool> used(strlen(matrix),false);
        if(str==NULL) return true;
        for(int i=0;i<rows;i++){
            for(int j=0;j<cols;j++){
                if(hasPathRecu(matrix, rows, cols, i, j, str, 0, used))
                    return true;
            }
        }
        return false;
     
    }
};

运行时间:3ms

占用内存:476k

动态规划法
public class Solution {
    public int movingCount(int threshold, int rows, int cols)
    {
        if(threshold<0)
            return 0;
        boolean [][] dp=new boolean[rows+1][cols+1];
        dp[0][0]=true;
        for(int i=1;i<=rows;i++){//初始化
            if(dp[i-1][0]&&canreach(threshold,i,0)){
                dp[i][0]=true;
            }else {
                dp[i][0]=false;
            }
        }
        for(int i=1;i<=cols;i++){//初始化
            if(dp[0][i-1]&&canreach(threshold,0,i)){
                dp[0][i]=true;
            }else {
                dp[0][i]=false;
            }
        }
        for(int i=1;i<=rows;i++){
            for(int j=1;j<=cols;j++){
                if((dp[i-1][j]&&canreach(threshold, i, j))||(dp[i][j-1]&&canreach(threshold, i, j))){
                    dp[i][j]=true;
                }else {
                    dp[i][j]=false;
                }
            }
        }
        int count=0;
        for(int i=0;i<rows;i++){
            for(int j=0;j<cols;j++){
                if(dp[i][j])
                    count++;
            }
        }      
    return count;      
    }
     public  boolean canreach(int threshold, int x, int y) {
            int sum = 0;
            while (x > 0) {
                sum += x % 10;
                x /= 10;
            }
            while (y > 0) {
                sum += y % 10;
                y /= 10;
            }
            return sum <= threshold;
        }
}
python
# -*- coding:utf-8 -*-

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值