AI-CV-1算法之旅


*此文章中算法来自leetcode、lintcode、牛客等…
*其中包括了算法工程师工作中遇到的问题
*大型互联网公司面试经典考题
*神经网路中的基础算法思想
*难度一般为中级到高级。

1.range-sum-query

1.1实现功能:

Given an integer array nums, find the sum of the elements between indices i and j (i ≤ j), inclusive.

Example:
Given nums = [-2, 0, 3, -5, 2, -1]

sumRange(0, 2) -> 1
sumRange(2, 5) -> -1
sumRange(0, 5) -> -3

1.2题目来源

题目来源(可点击):Leetcode-Problems

1.3代码实现

代码块如下:

//C++实现
class NumArray {
    int len;
    vector<int>cumSum;
public:
    NumArray(vector<int> nums) {
        len = nums.size();
        cumSum.resize(len+1,0);
        if(len){
            for(int i=1; i<=len ; i++){
                cumSum[i] = cumSum[i - 1] + nums[i - 1];
            }
        }
    }
    
    int sumRange(int i, int j) {
        return(cumSum[j+1] - cumSum[i]);
    }
};

/**
 * Your NumArray object will be instantiated and called as such:
 * NumArray* obj = new NumArray(nums);
 * int param_1 = obj->sumRange(i,j);
 */

1.4结果演示

Leetcode结果演示:

/**Finished
Runtime: 4 ms
Your input
["NumArray","sumRange","sumRange","sumRange"]
[[[-2,0,3,-5,2,-1]],[0,2],[2,5],[0,5]]
Output
[null,1,-1,-3]
Expected
[null,1,-1,-3]
*/

1.5 基本思想

基本思想:新建一个vector容器,新容器第i个空间,存放原容器前i-1个数字之和。即新容器存放原容器的积分值。此算法实现的时间复杂度算法复杂度为o(1)。

2.range-sum-query-2d

2.1实现功能:

Given a 2D matrix matrix, find the sum of the elements inside the rectangle defined by its upper left corner (row1, col1) and lower right corner (row2, col2).
图片矩阵·1
Range Sum Query 2D
The above rectangle (with the red border) is defined by (row1, col1) = (2, 1) and (row2, col2) = (4, 3), which contains sum = 8.

Example:
Given matrix = [
[3, 0, 1, 4, 2],
[5, 6, 3, 2, 1],
[1, 2, 0, 1, 5],
[4, 1, 0, 1, 7],
[1, 0, 3, 0, 5]
]

sumRegion(2, 1, 4, 3) -> 8
sumRegion(1, 1, 2, 2) -> 11
sumRegion(1, 2, 2, 4) -> 12

2.2题目来源

题目来源(可点击):Leetcode代码地址

2.3代码实现

代码块如下:

//C++实现
class NumMatrix{
private:
    vector<vector<int>>intergralMatrix;
public:
    NumMatrix(vector<vector<int>>matrix) {
        if (!matrix.size() || !matrix[0].size()) return;//判断输入是否合法
        int rows = matrix.size();   //矩阵行数
        int cols = matrix[0].size();       //矩阵列数
        intergralMatrix.resize(rows + 1,vector<int>(cols + 1, 0));//定义开辟空间的大小
        
        for (int r = 1; r<=rows; ++r){
            for(int c = 1; c <= cols; ++c){
                intergralMatrix[r][c] = -intergralMatrix[r - 1][c -1] +intergralMatrix[r - 1][c]+                                          intergralMatrix[r][c - 1] + matrix[r -1][c -1];
            }
        }
        return;
    }
    
    int sumRegion(int row1, int col1, int row2, int col2) {
        return intergralMatrix[row2 + 1][col2 + 1] + intergralMatrix[row1][col1] -
               intergralMatrix[row2 + 1][col1] -intergralMatrix[row1][col2 + 1];
    }
};

/**
 * Your NumMatrix object will be instantiated and called as such:
 * NumMatrix* obj = new NumMatrix(matrix);
 * int param_1 = obj->sumRegion(row1,col1,row2,col2);
 */

2.4结果演示

Leetcode结果演示:

/**
Your input
["NumMatrix","sumRegion","sumRegion","sumRegion"]
[[[[3,0,1,4,2],[5,6,3,2,1],[1,2,0,1,5],[4,1,0,1,7],[1,0,3,0,5]]],[2,1,4,3],[1,1,2,2],[1,2,2,4]]
Output
[null,8,11,12]
Expected
[null,8,11,12]
*/

2.5基本思想

基本思想:Note that the region Sum(OA)Sum(OA) is covered twice by both Sum(OB)Sum(OB) and Sum(OC)Sum(OC). We could use the principle of inclusion-exclusion to calculate Sum(ABCD)Sum(ABCD) as following:
Sum(ABCD) = Sum(OD) - Sum(OB) - Sum(OC) + Sum(OA) Sum(ABCD)=Sum(OD)−Sum(OB)−Sum(OC)+Sum(OA)

3.Sliding Window Maximum(max pooling)

3.1实现功能

此题为Hard级别(神经网路中二维Max pooling前导)
中文:给出一个可能包含重复的整数数组,和一个大小为 k 的滑动窗口, 从左到右在数组中滑动这个窗口,找到数组中每个窗口内的最大值。
English:Given an array of n integer with duplicate number, and a moving window(size k), move the window at each iteration from the start of the array, find the maximum number inside the window at each moving.
样例1:
输入:
[1,2,7,7,8]
3

输出:
[7,7,8]

解释:
最开始,窗口的状态如下:[|1, 2 ,7| ,7 , 8], 最大值为 7;
然后窗口向右移动一位:[1, |2, 7, 7|, 8], 最大值为 7;
最后窗口再向右移动一位:[1, 2, |7, 7, 8|], 最大值为 8.

样例2:
输入:
[1,2,3,1,2,3]
5

输出:
[3,3]

解释:
最开始,窗口的状态如下: [|1,2,3,1,2 | ,3] , 最大值为3;
然后窗口向右移动一位.[1, |2,3,1,2,3], 最大值为 3;
Challenge:时间复杂度o(n) time and 空间复杂度O(k) memory

3.2题目来源

题目来源(可点击):Lintcode代码地址

3.3代码实现

代码块如下:

//C++实现
class Solution {
public:
    /**
     * @param nums: A list of integers.
     * @param k: An integer
     * @return: The maximum number inside the window at each moving.
     */
    vector<int> maxSlidingWindow(vector<int> &nums, int k) {
        // write your code here
        vector<int> res;
        deque<int> index;              //指示最大值所在位置的下标
        int size = nums.size();        //原始数组的大小
        if(k > size) return res;       //如果不合法,直接返回
        if (!size) return res;
        for(int i = 0;i < k; ++i){     //初始化,第一个出窗口k
        //for语句完成之后,队列的头部永远存放数组最大值的索引
            while(!index.empty() && nums[i] >= nums[index.back()]){//如果index不空且
                index.pop_back();    //原始数组中当窗口继续往下移动先位置的值大于>=以队列末尾值为索引的数组值
            }                        //则把队列末尾的值剔出,再将当先索引i的值加到index末尾
            index.push_back(i);      //如果index为空,把i加入到双端队列尾部
        }                            //执行完结果:index存放当前窗口最大值的索引,若存放了多个索引,对应的
                                     //数组值是从大到小顺序排列,以[1,7,2,6,8]和[1,2,6,7,8]为例手写一些逻辑
        for(int i = k; i < size; ++i){       //
             res.push_back(nums[index.front()]);                     //将第一个窗口的最大值放入res容器中
             while(!index.empty() && nums[i] >= nums[index.back()]){ 
                 index.pop_back();
             }
             while(!index.empty() && index.front() <= i - k){  //只保留当前窗口的最大值[1,7,3,6,5]为例 k=3 这个语句比较难想,需要找数字规律
                 index.pop_front();
             }
             index.push_back(i);
         }
         res.push_back(nums[index.front()]);        
         return res;
    }
};

3.4 结果演示

Leetcode结果演示:

/**
Accepted
Input
[1,2,7,7,2]
3
Output
[7,7,7]
Expected
[7,7,7]
*/

3.5基本思想

基本思想:C++代码用双端队列deque数据结构来实现o(n)时间复杂度。
1.定义双端队列,用于存放将窗口的最大值索引。
2.随着窗口移动,最大值索引改变,难点在于分析数据的变化过程,找数字变化规律,写出程式语句。

4.sqrt 二分查找

4.1实现功能

Description
Implement int sqrt(int x).
Compute and return the square root of x.
Have you met this question in a real interview?
Example
Example 1:
Input: 0
Output: 0

Example 2:
Input: 3
Output: 1

Example 3:
Input: 4
Output: 2

Challenge
O(log(x))

4.2题目来源

题目来源(可点击)Lintcode代码地址

4.3代码实现

代码块如下:

class Solution {
public:
    /**
     * @param x: An integer
     * @return: The sqrt of x
     */
    int sqrt(int x) {
        // write your code here
         // classic binary search
      if (x <= 1) return x;
        int left = 0, right = x;
        while (left < right) {
            int mid = left + (right - left) / 2;
            if (x / mid >= mid) left = mid + 1;
            else right = mid;
        }
        return right - 1;
      }
};
//牛顿法
class Solution {
public:
    /**
     * @param x: An integer
     * @return: The sqrt of x
     */
        long a = x;
        long eps = 0.00001;
        while(a*a-x>eps){
            a = 0.5*(a + x/a);
        }
        return a;
      }
};

4.4结果演示

Accepted
Powered by LintCode FlashJudge
Input
4
Output
2
Expected
2

Input
3
Output
1
Expected
1

4.5基本思想

方法1:首先选择x/2作为候选值,将其平方与x比较大小。为了缩短查找时间,我们采用二分搜索法来找平方根。
方法2:牛顿法。
二分搜索法参考地址1
二分搜索法参考地址2
牛顿法参考地址

5.powx-n

5.1实现功能

Description
Implement pow(x, n). (n is an integer.)

Example
Example 1:

Input: x = 9.88023, n = 3
Output: 964.498
Example 2:

Input: x = 2.1, n = 3
Output: 9.261
Example 3:

Input: x = 1, n = 0
Output: 1
Challenge
O(logn) time

5.2题目来源

题目来源:lintcode代码地址

5.3代码实现

//递归操作
class Solution {
public:
    /**
     * @param x: the base number
     * @param n: the power number
     * @return: the result
     */
    double myPow(double x, int n) {
        write your code here
         int res = 1;
        if (n == 0){
            return 1;
        }
        if (n < 0){
            n = -n;
            x = 1/x;
        }
        return !(n & 1) ? myPow(x*x, n/2): x *myPow(x *x, n/2);
        
    }
};
//位操作(对整数次幂运算)运算速度很快
class Solution {
public:
    /**
     * @param x: the base number
     * @param n: the power number
     * @return: the result
     */
    double myPow(double x, int n) {
        int res = 1;
        int tmp = x;
        while(n){
            if (n & 1){
                res *= tmp;
            }
            tmp *=tmp;
            n >>= 1; //右移 n= n>>1 右移是除以2,左移是乘以2
        }
        return res;
    }
};
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值