29. 两数相除 没想明白
给定两个整数,被除数 dividend 和除数 divisor。将两数相除,要求不使用乘法、除法和 mod 运算符。
返回被除数 dividend 除以除数 divisor 得到的商。
示例 1:
输入: dividend = 10, divisor = 3输出: 3示例 2:
输入: dividend = 7, divisor = -3输出: -2说明:
被除数和除数均为 32 位有符号整数。除数不为 0。假设我们的环境只能存储 32 位有符号整数,其数值范围是 [−231, 231 − 1]。本题中,如果除法结果溢出,则返回 231 − 1。
第一版 个人版本,超时了
intdivide(intdividend, intdivisor) {//被除数和除数都是整数,且结果不能溢出
if (dividend==INT_MIN&&divisor==-1) returnINT_MAX;
if (dividend==0) return0;
intsignal=-1;
if ((dividend>0&&divisor>0) || (dividend<0&&divisor<0)) signal=1;
if (signal==1)
{
signal=0;
if (dividend>0)
{
while (dividend>=0&&signal<=INT_MAX) {
dividend-=divisor;
signal+=1;
}
}
else {
while (dividend<=0&&signal<=INT_MAX) {
dividend-=divisor;
signal+=1;
}
}
returnsignal==INT_MAX?INT_MAX:signal-1;
}
else
{
signal=0;
if (dividend>0)
{
while (dividend>=0&&signal>=INT_MIN) {
dividend+=divisor;
signal-=1;
}
}
else {
while (dividend<=0&&signal>=INT_MIN) {
dividend+=divisor;
signal-=1;
}
}
returnsignal==INT_MIN?INT_MIN : signal+1;
}
}
34. 在排序数组中查找元素的第一个和最后一个位置
第一版
最后执行的输入为
[1,2,2]2
返回的错误为:AddressSanitizer: heap-buffer-overflow on address 0x60200000053c at pc 0x0000004066e1 bp
这是数组越界的错误
左看右看也没找到越界在哪里
vector<int>searchRange(vector<int>&nums, inttarget) {
if (nums.empty() ||nums[0] >target||nums[nums.size() -1] <target) returnvector<int>{-1, -1};//当nums为空或者最小值也大于target或者最大值依然//小于target,直接返回
intminIndex,maxIndex,mid, low=0, high=nums.size() -1;
while (low+1<high) {
mid=low+ (high-low) /2;
if (nums[mid] ==target) //找到目标做处理
{
while (nums[mid] ==target)
{
mid--;
}
minIndex=mid+1;
mid++;
while (nums[mid] ==target)//越界在这里
{
mid++;
}
maxIndex=mid-1;
return { minIndex,maxIndex };
}
elseif (nums[mid] >target) {
high=mid;
}
else { low=mid; }
}
if (nums[low] ==target) {
if (nums[high] ==target) return { low,high };
else
return { low,low };
}
elseif (nums[high] ==target) {
return { high,high };
}
else
return { -1,-1 };
}
越界解析 :nums[2]为最后一个元素,等于target,此时再进入循环,mid++,所以访问nums[3]即为越界,所以判断条件不够,不止上届,同样的下界也应该增加判断条件
第二版
vector<int>searchRange(vector<int>&nums, inttarget) {
if (nums.empty() ||nums[0] >target||nums[nums.size() -1] <target) return {-1, -1};
intminIndex,maxIndex,mid, low=0, high=nums.size() -1;
while (low+1<high) {
mid=low+ (high-low) /2;
if (nums[mid] ==target)
{
while (mid>=0&&nums[mid] ==target)//这里增加界限判断,不至于越界访问
{
mid--;
}
if (mid<0) {
minIndex=0; mid=0;
}
else
{
minIndex=++mid;
}
while (mid<nums.size() &&nums[mid] ==target)//这里增加界限判断,不至于越界访问
{
mid++;
}
if (mid==nums.size()) {//虽然此时满足mid==nums.size(),但10并不是target
maxIndex=nums.size()-1;
}
else
{
minIndex=--mid;
}
return { minIndex,maxIndex };
}
elseif (nums[mid] >target) {
high=mid;
}
else { low=mid; }
}
if (nums[low] ==target) {
if (nums[high] ==target) return { low,high };
else
return { low,low };
}
elseif (nums[high] ==target) {
return { high,high };
}
else
return { -1,-1 };
}
最后输入为输入:[5,7,7,8,8,10] 8
输出:[3,5]
预期:[3,4]
此时跟上面又有不同,这里10为末尾元素,也不是目标,10的前面一个是目标元素,虽然此时mid=nums.size(),,但是mid=nums.size()-1=5,还是指的是10,所以如果最后到了数组末尾,还需要再加判断
第三版本
vector<int>searchRange(vector<int>&nums, inttarget) {
if (nums.empty() ||nums[0] >target||nums[nums.size() -1] <target)
return { -1, -1 };//当nums为空或者最小值也大于target或者最大值依然小于target,直接返回
intminIndex, maxIndex, mid, low=0, high=nums.size() -1;
while (low+1<high) {//在数组内部查找
mid=low+ (high-low) /2;
if (nums[mid] ==target)//招到了target
{
inttempMid=mid;//双份mid更方便一些,一份查找左边界,一份查找有边界
while (mid>=0&&nums[mid] ==target)//左侧查找边界
{
mid--;
}
if (mid<0) { //到了数组头了,还需要再加判断头元素是不是target
if (nums[0] ==target) minIndex=0;
else
minIndex=mid+2;
}
else//没到数组头,说明头元素不是target
minIndex=++mid;
while (tempMid<=nums.size() -1&&nums[tempMid] ==target)//右侧查找边界
{
tempMid++;
}
if (tempMid==nums.size()) {//到了数组尾部了,还需要再加判断尾部元素是不是target
if (nums[nums.size() -1] ==target) maxIndex=nums.size() -1;
else
maxIndex=nums.size() -2;
}
else//没到数组尾部,说明尾部元素不是target
maxIndex=--tempMid;
return { minIndex,maxIndex };
}
elseif (nums[mid] >target) {
high=mid;
}
else { low=mid; }
}
if (nums[low] ==target) {//没在数组除了low和high的位置找到target,再处理
if (nums[high] ==target) return { low,high };
else
return { low,low };
}
elseif (nums[high] ==target) {
return { high,high };
}
else
return { -1,-1 };
}
执行用时 :8 ms, 在所有 C++ 提交中击败了95.18%的用户
内存消耗 :10.4 MB, 在所有 C++ 提交中击败了76.75%的用户