搜索插入位置这个题,没啥好说的,就是一个非常简单的二分法。直接遍历虽然说也是个O(n),但二分法是个O(logn),能想到好办法还是尽量用好办法吧。这也是难得的能一遍AC的题目。
不过我注意到一件非常有意思的事,我看基本上所有人写二分法都是用left和right进行比较,while(left<=right)
,但我特别喜欢拿left和mid比较,while(left < mid)
,也不知道为什么:
/**
* ------result------
* memory: 8.7 MB (90%)
* speed: 4 ms (98%)
*/
int searchInsert(vector<int> &nums, int target)
{
auto b = 0;
auto e = nums.size();
auto mid = (b + e) / 2;
while (b < mid)
{
if (target == nums[mid])
{
return mid;
}
else if (target > nums[mid])
{
b = mid;
}
else
{
e = mid;
}
mid = (b + e) / 2;
}
return target > nums[b] ? b + 1 : b;
}
区域和检索,坦率地讲,其实也并不难。说是动态规划吧,好像确实是那么回事;但是这种计算应该是很自然的。不过我觉得这道题背后的东西在生产环境中能用上,因为题目里强调了会多次调用这个函数,也就促使我们去进行缓存;不然,每次重新计算一遍,这谁顶得住。
缓存机制还是挺重要的。仔细想想,很多解法(尤其是那种空间换时间的解法),似乎就是通过保存状态来进行优化的。动态规划似乎也是这样?通过保存之前的状态,来得出全局的最优解。
class NumArray {
private:
int *sums = nullptr;
public:
/**
* ------result------
* memory: 17.2 MB (60%)
* speed: 32 ms (97%)
*/
NumArray(vector<int> &nums)
{
int n = nums.size();
sums = new int[n + 1]{0};
for (auto i = 1; i <= n; ++i)
{
sums[i] = sums[i - 1] + nums[i - 1];
}
}
int sumRange(int i, int j)
{
return sums[j + 1] - sums[i];
}
};