704. 二分查找
文档讲解:
代码随想录
视频讲解:手把手带你撕出正确的二分法 | 二分查找法 | 二分搜索法 | LeetCode:704. 二分查找_哔哩哔哩_bilibili
看到题目后第一想法:正常二分
看完代码随想录后的想法:居然有两个二分
题目总结:
//左闭右闭 class Solution { public int search(int[] nums, int target) { int l = 0,r = nums.length-1; while(l<=r){ int i = (l+r)/2; if(nums[i] == target) return i; if(nums[i] < target) l = i+1; else r = i-1; } return -1; } } //左闭右开 class Solution { public int search(int[] nums, int target) { int l = 0,r = nums.length-1; int s; while(l<r){ s = (r+l)/2; if(nums[s] == target) return s; if(nums[s] > target) r = s; else l = s+1; } return -1; } }两个二分的区别就是区间的选取不同
为什么都是左闭?因为自动向下取整,所以左边一定是闭区间,右边则需要加上等于才算闭区间
当左闭右闭时包括中间元素,所以左右指针不包括中间元素
当左闭右开时不包括中间元素,所以右指针需要包括中间元素,而左指针因为向下取整天然包括,就不需要包括中间了
当选取左闭右闭区间时,循环判断条件为while (left <= right),目标在左区间时if (nums[middle] > target) right = middle - 1;
当选取左闭右开区间时,循环判断条件为while (left < right),目标在左区间时if (nums[middle] > target) right = middle;
若第一种:while (left <= right)且right = middle时[-1,0,3,5,9,12],target =2会使l = r = 2,都指向3,此时中间值大于2但r不变,无限循环下去
若第二种:为while (left < right)且right = middle-1;时若输入的数组为【5】target=5,则会返回-1
27. 移除元素
文档讲解:
代码随想录
视频讲解:数组中移除元素并不容易! | LeetCode:27. 移除元素_哔哩哔哩_bilibili
看到题目后第一想法:找到对应值,然后将后面元素前移
看完代码随想录后的想法:快慢指针和双指针
题目总结:
//我的 class Solution { public int removeElement(int[] nums, int val) { int l = 0,r = 0,len = nums.length; if(len == 0) return 0; while(l<len && r<len){ while(r<len && nums[r] == val){ r++; } if(r<len){ nums[l] = nums[r]; l++;r++; } } return l; } } //标准快慢指针 class Solution { public int removeElement(int[] nums, int val) { int slow = 0; // 慢指针:下一个存放有效元素的位置 // 快指针遍历整个数组 for (int fast = 0; fast < nums.length; fast++) { // 遇到不等于 val 的元素,就放到慢指针位置 if (nums[fast] != val) { nums[slow] = nums[fast]; slow++; } } return slow; } } //标准双向指针(适配元素可打乱情况) class Solution { public int removeElement(int[] nums, int val) { int left = 0, right = nums.length - 1; while (left <= right) { if (nums[left] == val) { nums[left] = nums[right]; right--; } else { left++; } } return left; } } //我的双向指针 class Solution { public int removeElement(int[] nums, int val) { int l = 0,r = nums.length-1; while(l<=r){ if(l == r){ if(nums[l] != val) return l+1; else return l ; } while(nums[l] != val && l<r) l++; while(nums[r] == val && r>l) r--; if(l<r) nums[l++] = nums[r--]; } return l; } }快慢指针:设立快慢指针,遍历数组,刚开始都指向0,if快指针没遇到目标值,就将快指针位置的值赋予慢指针,否则快指针+1
双指针:一左一右两个指针,循环条件为左指针小于等于右指针,左指针找val,右指针找非val,找到后交换位置
自己的写法都是批量式处理的逻辑,这样的话会循环套循环,容易出错,标准写法都是每次循环只处理一件事,逻辑简单,代码量也少
977.有序数组的平方
文档讲解:
代码随想录
视频讲解:双指针法经典题目 | LeetCode:977.有序数组的平方_哔哩哔哩_bilibili
看到题目后第一想法:先平方,后排序
看完代码随想录后的想法:双指针
题目总结:
class Solution { public int[] sortedSquares(int[] nums) { int [] res = new int [nums.length]; int l = 0,r = nums.length-1; while(l<nums.length){ nums[l] = nums[l]*nums[l]; l++; } l = 0; int i = r; while(l<=r){ if(nums[l]>nums[r]) res[i--] = nums[l++]; else res[i--] = nums[r--]; } return res; } }双指针:先设立一个新数组(装最后的返回值),在原来的数组中先都平方,然后最大值肯定在两端,此时,设立双指针,一左一右,进入循环,条件为左小于等于右,找最大值,放入新数组末尾,然后向中心移动指针。
鉴于作者水平有限,文章可能存在错误
如有指正,十分感谢