704.二分查找
题目的第一想法:
这道题对于我来说已经做过很多很多遍了,跟着carl哥学的一直坚持左闭右开或者左闭右闭,在任何时候都一样就可以完美应对这道题保证不出错!
实现代码:
class Solution { public: int search(vector<int>& nums, int target) { // 左闭右开版本 int res; int left = 0; int right = nums.size(); // left < right 因为左闭右开在left等于right时不满足条件,所以说不能相等 while(left < right) { int mid = (left + right) / 2; if(nums[mid] > target) { // 右开,右边mid中值取不到 right = mid; } else if(nums[mid] < target) { // 左闭,mid取不到所以说加一 left = mid + 1; } else { // 这种情况已经相等返回答案了 return mid; } } // 遍历完了还没找到返回-1 return -1; } };
class Solution { public: int search(vector<int>& nums, int target) { // 左闭右闭版本 int left = 0; int right = nums.size() - 1; // 左闭右闭,当left等于right的时候满足条件,必须使用<= while(left <= right) { int mid = (left+right)/2; if(nums[mid] > target) { // 右闭,mid位置不满足条件所以减一 right = mid - 1; } else if(nums[mid] < target) { // 左闭,mid位置不满足条件所以加一 left = mid + 1; } else { // 满足情况,直接返回答案 return mid; } // 不满足条件,返回-1 } return -1; } };
遇到的问题:
在查看carl哥代码的时候,发现自己小细节出现了问题,carl哥代码如下:
// 版本一 class Solution { public: int search(vector<int>& nums, int target) { int left = 0; int right = nums.size() - 1; // 定义target在左闭右闭的区间里,[left, right] while (left <= right) { // 当left==right,区间[left, right]依然有效,所以用 <= int middle = left + ((right - left) / 2);// 防止溢出 等同于(left + right)/2 if (nums[middle] > target) { right = middle - 1; // target 在左区间,所以[left, middle - 1] } else if (nums[middle] < target) { left = middle + 1; // target 在右区间,所以[middle + 1, right] } else { // nums[middle] == target return middle; // 数组中找到目标值,直接返回下标 } } // 未找到目标值 return -1; } };
// 版本二 class Solution { public: int search(vector<int>& nums, int target) { int left = 0; int right = nums.size(); // 定义target在左闭右开的区间里,即:[left, right) while (left < right) { // 因为left == right的时候,在[left, right)是无效的空间,所以使用 < int middle = left + ((right - left) >> 1); if (nums[middle] > target) { right = middle; // target 在左区间,在[left, middle)中 } else if (nums[middle] < target) { left = middle + 1; // target 在右区间,在[middle + 1, right)中 } else { // nums[middle] == target return middle; // 数组中找到目标值,直接返回下标 } } // 未找到目标值 return -1; } };
卡哥在处理middle中值的时候,使用了一下方法:
int middle = left + ((right - left) >> 1); int middle = left + ((right - left) / 2);// 防止溢出 等同于(left + right)/2
使用(right - left)>> 1右移运算符相对于除以2,相当于left加上中间值,就等同于(left + right)/ 2 ,但只有可以防止left+right时溢出,非常的细节,小本本记上!!
27.移除元素
题目的第一想法:
这到题也是经典中的经典,想当初在上数据结构的时候还在课堂上跟同学将过这个方法,导致同学都觉得我是大神,其实就是一个才学的小菜鸟罢了,这道题懂得这种换位思考就很好做,不考虑怎么去移除元素(数组移除元素需要移动后面大量元素),只需要考虑需要哪些元素满足条件然后保留下来即可。
代码实现:
class Solution { public: int removeElement(vector<int>& nums, int val) { // slow指针表示与当前val不相等元素要插入的下标 int slow = 0; // fast指针表示所遍历的元素下标,默认都从0开始 int fast = 0; // nums.size()的值不会改变,这样ok while(fast < nums.size()) { // 不相等,表示不需要移除,放在slow下标 if(nums[fast] != val) { nums[slow++] = nums[fast]; } // 相等情况不做操作即可,相当与只要满足条件的元素 fast++; } // 由于下标比长度小1,但slow是要插入的下标,所以说刚好对应其长度 return slow; } };
遇到的问题:
无