持续创作,加速成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第7天,点击查看活动详情
废话不多说,先摆上704代码
class Solution {
public int search(int[] nums, int target) {
int left = 0;
int right = nums.length - 1;
while(left <= right){ //这个循环结构老是忘记写,而且是<=
int mid = left + (right - left);
if (target == nums[mid]){
return mid;
} else if(target < nums[mid]) {
right = mid - 1;
} else {
left = mid + 1;
}
}
return -1;
}
}
- 关键的思想就是小了,右边界变成中间-1;大了,左边界变成中间+1;
- 可以用迭代但是明显会慢一点,所以直接使用了个while循环进行判定,但是while循环我自己老是忘记写,要记得。如果没有左边界要小于等于右边界的话,就会出去然后报错。
27一开始卡住了,傻逼地认为还是需要弄个二分查找,做傻题目了吧
27这道题,这道题最优解法就是双指针,相当于用空间换时间。如果用暴力解法两层循环也行。数组有个特点就是创建后你删除某个元素,它所占据地空间还是在那,只能采用覆盖的方法。
Java代码如下:
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;
}
}
209这道题,先自己用了两层循环的滑动窗口导致超时了
class Solution {
public int minSubArrayLen(int target, int[] nums) {
int left =0;
// int sum = 0
int n = 100000;
int right = 0;
while(left < nums.length){
int sum = 0;
for(right = left;right < nums.length;right++){
sum += nums[right]; //这里的先后顺序问题
if(sum>=target){
int num = right - left + 1;
// return num;
if(n>num){
n = num;
// 看懂了,可恶,我没有加left,导致一直循环
}
break;
}
}
left++;
}
return n == 100000 ? 0 : n;
}
}
过了测试用例18个,但是专门检测是否超时的就卡住了。明天再看,再放正确解答上来
滑动窗口的精妙之处在于根据当前子数组和的大小,不断调节子数组的起始位置,从而将时间复杂度从O(n方)降为O(n)
class Solution {
public int minSubArrayLen(int target, int[] nums) {
int left =0;
// int sum = 0
int n = 1000000;
int right = 0;
int sum = 0;
for(right = 0; right<nums.length;right++){
sum += nums[right];
while(sum>=target) {
if(n>(right - left + 1)){
n = (right - left + 1);
}
sum -= nums[left++]; //这里是关键点,缩小窗口大小,也就是滑动窗口的核心。
}
}
return n == 1000000 ? 0 : n;
}
}