Cool说丨力扣29/34

简介: 关注博主。获取更多知识

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%的用户


目录
相关文章
|
人工智能 C# C++
Cool说丨力扣153、454
153. 寻找旋转排序数组中的最小值 454. 四数相加 II
135 1
|
C# C++
Cool说丨力扣287/792/378
关注博主,获取更多知识
112 0
|
C# C++ 索引
Cool说丨力扣162
162. 寻找峰值
100 0
|
存储 C# C++
Cool说丨力扣392
392. 判断子序列
76 0
|
C# C++
Cool说丨力扣744、704
744. 寻找比目标字母大的最小字母 704. 二分查找
111 0
|
C#
Cool说丨力扣475
475. 供暖器
118 0
|
机器学习/深度学习 算法 C#
Cool说丨力扣202
202. 快乐数
104 0
|
C#
Cool说丨力扣167
167. 两数之和 II - 输入有序数组
73 0
|
C# C++
Cool说丨力扣374、441
441. 排列硬币 374. 猜数字大小
98 0
|
C# C++
Cool说丨力扣367
367. 有效的完全平方数
249 0