704.二分查找
暴力解法:
public class Solution {
public int Search(int[] nums, int target) {
for(int i=0;i<nums.Length;i++)
{
if(nums[i]==target)
{
return i;
}
}
return -1;
}
}
采用单层For循环遍历整个数组,遍历完成之前遇到Target则直接返回当前下标i的值,如果遍历完成则说明未找到Target,则按题目要求返回-1,时间复杂度O(n)。
二分法:
public class Solution {
public int Search(int[] nums, int target) {
int left = 0;
int right = nums.Length;
int mid = (right - left)/2+left;
while (left<right)
{
if (nums[mid] > target)
{
right = mid;
mid = (right - left)/2 + left;
}
else if (nums[mid] < target)
{
left = mid+1;
mid = (right - left)/2 + left;
}
else
{
return mid;
}
}
return -1;
}
}
提到二分法就想到不断将区间二分缩小,第一反应可能是采用递归方法,但是一个While()循环则可以实现,并且时间复杂度为O(log n) 。首先我们定义两个指针变量Left和Right分别指向数组的起始和结束位置,我们定义了一个中间变量Mid,用于计算数组的中间索引。While循环条件一般有两种Left<Right和Left<=Right,分别对应边数组范围左闭右开和左闭右闭,两种不同的情况将会进一步影响下面二分过程中Left和Right的赋值情况。整体过程分为三个判断部分,Target>Mid位值,Target<Mid位值,Target=Mid位值,分别进行逻辑处理即可,更新左右指针时Mid是否+/-1与上面情况挂钩。
二分法局限性:依赖于数组且数组必须有序且各元素均唯一,数据量过小或过大都不适合使用二分查找。
27.移除元素
快慢指针:
public class Solution {
public int RemoveElement(int[] nums, int val) {
int slow=0;
int fast=0;
for(fast=0;fast<nums.Length;fast++)
{
if(val!=nums[fast])
{
nums[slow++]=nums[fast];
}
}
return slow;
}
}
采用快慢指针时间复杂度O(n),快指针For循环遍历数组并判断移除元素Val是否与该位置元素值相同,相同则Fast指针继续向后遍历,Slow指针则来到相等处等待下一个不为Val元素到来,如果不相同Slow则被Fast更新赋值,结束循环,返回Slow,此时Slow值为新的移除后数组的长度。