🌈hello,你好鸭,我是Ethan,西安电子科技大学大三在读,很高兴你能来阅读。
✔️目前博客主要更新Java系列、项目案例、计算机必学四件套等。
🏃人生之义,在于追求,不在成败,勤通大道。加油呀!
🔥个人主页:Ethan Yankang
🔥推荐:史上最强八股文 || 一分钟看完我的上千篇博客
🔥温馨提示:划到文末发现专栏彩蛋 点击这里直接传送
🔥本篇概览:数据结构与算法 || 详细讲解了代码随想录二刷的数组篇。🌈⭕🔥
【计算机领域一切迷惑的源头都是基本概念的模糊,算法除外】
🌈序言
算法乃我长久之志也,此关必过。如今二刷代码随想录,必然收获良多,加油不懈怠!
本次只写题目+代码实现(主要的点全都写在代码注释里面),多题合一。
🔥 前一篇章
题目:
704. 二分查找
给定一个 n
个元素有序的(升序)整型数组 nums
和一个目标值 target
,写一个函数搜索 nums
中的 target
,如果目标值存在返回下标,否则返回 -1
。
已经统一了二分法使用对称的写法left<=right
注意这里一定要使用((right-left)>>1)将整体括起来,因为这里>>运算符优先级低于+
class Solution {
public int search(int[] nums, int target) {
// 避免当 target 小于nums[0] nums[nums.length - 1]时多次循环运算
if (target < nums[0] || target > nums[nums.length - 1]) {
return -1;
}
int left = 0, right = nums.length - 1;
while (left <= right) {
int mid = left + ((right - left) >> 1);
if (nums[mid] == target)
return mid;
else if (nums[mid] < target)
left = mid + 1;
else if (nums[mid] > target)
right = mid - 1;
}
return -1;
}
}
35. 搜索插入位置
给定一个排序数组和一个目标值,在数组中找到目标值,并返回其索引。如果目标值不存在于数组中,返回它将会被按顺序插入的位置。
请必须使用时间复杂度为 O(log n)
的算法
class Solution {
public int searchInsert(int[] nums, int target) {
int length=nums.length;
int left=0;
int right=length-1;
while (left<=right){
int middle=left+((right-left)>>1);
if (nums[middle]==target){
return middle;
} else if (nums[middle]>target){
right=middle-1;
} else if (nums[middle]<target){
left=middle+1;
}
}
或者return left(因为最后退出循环前一步的情形一定是left==right。
无论是left前移还是right后移,位置都是最后一个(最为匹配。二分法的精髓本就是步步最佳匹配。
所以返回left与right+1都是一样的))
// return right+1;
return left;
}
}
27. 移除元素
给你一个数组 nums
和一个值 val
,你需要 原地 移除所有数值等于 val
的元素。元素的顺序可能发生改变。然后返回 nums
中与 val
不同的元素的数量。
假设 nums
中不等于 val
的元素数量为 k
,要通过此题,您需要执行以下操作:
- 更改
nums
数组,使nums
的前k
个元素包含不等于val
的元素。nums
的其余元素和nums
的大小并不重要。 - 返回
k
。
原地、移除元素、不使用额外空间==>100%双指针
class Solution {
public int removeElement(int[] nums, int val) {
int length=nums.length;
int slowIndex=0;
int fastIndex=0;
while (fastIndex<length){
if(nums[fastIndex]!=val){
nums[slowIndex++]=nums[fastIndex];
}
fastIndex++;
}
return slowIndex;
}
}
34. 在排序数组中查找元素的第一个和最后一个位置
给你一个按照非递减顺序排列的整数数组 nums
,和一个目标值 target
。请你找出给定目标值在数组中的开始位置和结束位置。
如果数组中不存在目标值 target
,返回 [-1, -1]
。
你必须设计并实现时间复杂度为 O(log n)
的算法解决此问题。
这里分而治之,左右边界分开查找
最后target可能在中间的情况一定要判断(rightBorder-leftBorder>1),因为如果target没有的话,会出现RB<LB的情况,而这种情况,返回[-1,-1]
例如 1 2 3 5 6 判断4 ==》边界范围是RB=2,值为3;LB=3,值为5,所以是[3,2]显然是错的。
class Solution {
int leftBorder=-1;
int rightBorder=-1;
public int[] searchRange(int nums[] ,int target) {
int length = nums.length;
// 先判断特殊情况.在两边的情况去除之
if(length==0)return new int[]{-1,-1};
if(target < nums[0] || target > nums[length - 1]) return new int[]{-1, -1};
leftBorder = getLeftBorder(nums, target);
rightBorder = getRightBorder(nums, target);
// 这里正确答案+1,-1的情况是因为跳出循环的时候索引处一定不是本元素
return (rightBorder-leftBorder>1)?new int[]{leftBorder+1, rightBorder-1}:new int[]{-1,-1};
}
private int getLeftBorder(int[] nums, int target) {
int left = 0;
int right = nums.length - 1;
while (left <= right) {
int mid = left + ((right - left) >> 1);
if (nums[mid] >= target) {
right = mid - 1;
leftBorder = right;
} else {
left = mid + 1;
}
}
return leftBorder;
}
private int getRightBorder(int[] nums, int target) {
int left = 0;
int right = nums.length - 1;
while (left <= right) {
int mid = left + ((right - left) >> 1);
if (nums[mid] <= target) {
left = mid + 1;
rightBorder=left;
} else {
right = mid - 1;
}
}
return rightBorder;
}
}
📣非常感谢你阅读到这里,如果这篇文章对你有帮助,希望能留下你的点赞👍 关注❤收藏✅ 评论💬,大佬三连必回哦!thanks!!!
📚愿大家都能学有所得,功不唐捐!
👇下面是专栏彩蛋系列,你会喜欢的!(为了避免影响算法的简洁与优美,这里直接将之前的几十个专栏简化为3个部分,不过你点击开后发现惊喜。)👇
💖💖💖💖💖💖💖💖💖💖💖💖💖💖💖💖💖💖
热门专栏
💖💖💖💖💖💖💖💖💖💖💖💖💖💖💖💖💖💖