二分法查找,力扣704
自己一开始第一想法写的代码。
class Solution {
public int search(int[] nums, int target) {
int left = 0;
int right = nums.length;
int middle = (int)(left + right)/2;
while(left < right){
if(nums[middle] == target){
return middle;
}
else if(middle == left){
return -1;
}
else if(nums[middle] > target){
right = middle;
middle = (int)(left + right)/2;
}
else if(nums[middle] < target){
left = middle;
middle = (int)(left + right)/2;
}
}
return -1;
}
}
但是这有点投机取巧,没有理解这个方法中的一个关键问题,就是查找的定义域,无论是两边都闭合还是左闭右开核心都是查找了一个区域之后再查找的区域要完全略过已经确定没有的区域,接下来理解后的代码是这样的。
class Solution {
public int search(int[] nums, int target) {
int left = 0;
int right = nums.length;
int middle = (int)(left + right)/2;
while(left < right){
middle = (int)(left + right)/2;
if(nums[middle] > target){
right = middle ;
}
else if(nums[middle] < target){
left = middle + 1;
}
else return middle;
}
return -1;
}
}
这个感觉就很好。
2. 移除元素
我一开始想到的办法,暴力解法
class Solution {
public int removeElement(int[] nums, int val) {
int length = nums.length;
for(int i = 0;i < length;i++){
if(nums[i] == val){
for(int j = i;j < length - 1;j++){
nums[j] = nums[j+1];
}
length--;
i--;
}
}
return length;
}
}
写的时候还是有遇到一些小问题,比如这个length要在数组交换位子之后再减,不然你就会出现最后一个数还没来得及交换的情况。
还有就是要记得在进行了一次覆盖之后要进行i--,把这个位置往前移动一次,不然你就会跳过下一个数了。
双指针解法
class Solution {
public int removeElement(int[] nums, int val) {
int slow = 0;
for(int fast = 0; fast < nums.length;fast++){
if(nums[fast] != val){
nums[slow] = nums[fast];
slow++;
}
}
return slow;
}
}
这个方法特别巧妙,我在看了一半视频之后就理解了,所以写的也是很快,值得纪念。这个解法的核心就是,快指针指向我们需要的元素,而慢指针指向需要更新的位子。这样就不需要两个循环来覆盖了。