AI-CV arithmetic Tips
*此文章中算法来自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).
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;
}
};