704. 二分查找 简单题
题意:
在有序且无重复元素的数组中查找目标值target,找到返回其下标,没有找到返回-1 ==》可以考虑使用二分法
二分法时间复杂度: O(logn)
直接遍历数组查找时间复杂度: O(n)
其次,使用二分法时,注意区间开闭情况
var search = function(nums, target) {
// right是数组最后一个数的下标,num[right]在查找范围内,是左闭右闭区间
let mid, left = 0, right = nums.length - 1;
// 当left=right时,由于nums[right]在查找范围内,所以要包括此情况
while (left <= right) {
// 位运算 + 防止大数溢出
mid = left + ((right - left) >> 1);
// 如果中间数大于目标值,要把中间数排除查找范围,所以右边界更新为mid-1;如果右边界更新为mid,那中间数还在下次查找范围内
if (nums[mid] > target) {
right = mid - 1; // 去左面闭区间寻找
} else if (nums[mid] < target) {
left = mid + 1; // 去右面闭区间寻找
} else {
return mid;
}
}
return -1;
};
相关题目推荐
27. 移除元素 简单题
暴力解法
var removeElement = function(nums, val) {
let len = nums.length;
for(let i = 0; i < len; i++) {
// 遇到待删除元素 ==》 原地删除该元素
if(nums[i] === val) {
let j = i+1;
while(j < len) {
nums[j-1] = nums[j];
j++;
}
len--;
i--; // i一定要减1(考虑出现删除连续的两个及以上的值时)
}
}
return len;
};
双指针法
var removeElement = function(nums, val) {
let slow = 0, fast = 0;
while(fast < nums.length) {
// 保留数值不等于val的元素
if(nums[fast] !== val) {
nums[slow] = nums[fast];
slow++;
}
// 不论当前元素是否保留,fast都往后走
fast++;
}
return slow;
};
相关题目推荐
- 26.删除排序数组中的重复项
- 283.移动零
- 844.比较含退格的字符串
- 977.有序数组的平方
977. 有序数组的平方 简单题
方法一: 暴力排序
时间复杂度: O(n+nlogn) ==> O(nlogn)
空间复杂度: O(1)
var sortedSquares = function(nums) {
for(let i = 0; i < nums.length; i++) {
nums[i] = nums[i] * nums[i];
}
nums.sort((a,b) => a-b);
return nums;
};
方法二: 双指针法
时间复杂度: O(n)
空间复杂度: O(n)
var sortedSquares = function(nums) {
let len = nums.length;
let i = 0, j = len - 1, k = len - 1;
// res新数组,k从下标len到0一个个存当前最大值
let res = new Array(len).fill(0);
// i,j 双指针, 从数组两端找平方值最大者
while(i <= j) {
let left = nums[i] * nums[i];
let right = nums[j] * nums[j];
if(left > right) {
res[k--] = left;
i++;
}else {
res[k--] = right;
j--;
}
}
return res;
};
209. 长度最小的子数组 中等题
含有 n 个正整数的数组和一个正整数 target
找出该数组中满足其和 ≥ target 的长度最小的 连续子数组 [numsl, numsl+1, ..., numsr-1, numsr] ,并返回其长度. 不存在符合条件的子数组,返回 0.
方法一:暴力解法 居然可以过
var minSubArrayLen = function(target, nums) {
let res = nums.length + 1;
let sum = 0;
for(let i = 0; i < nums.length; i++) {
// 子序列起点为i
sum = 0;
for(let j = i; j < nums.length; j++) {
sum += nums[j];
if(sum >= target) {
res = res < (j-i+1) ? res : (j-i+1);
break;
// 因为是找符合条件最短的子序列,所以一旦符合条件就break
}
}
}
// 如果res没有被赋值,就返回0,说明没有符合条件的子序列
return res === nums.length + 1? 0 : res;
};
方法二:滑动窗口
var minSubArrayLen = function(target, nums) {
let i = 0, j = 0,len = nums.length;
let sum = 0;
let min = len + 1; // 子数组最大不会超过自身
while(j < len) {
sum += nums[j];
// 窗口滑动
while(sum >= target) {
// 闭区间 [i, j]
if(min > (j-i+1)) min = j-i+1;
sum -= nums[i];
i++;
}
j++;
}
return min == len + 1? 0: min;
};
相关题目推荐
59. 螺旋矩阵 II 中等题 这题要多写 !!!
方法一
var generateMatrix = function(n) {
let res = Array.from(Array(n), () => Array(n).fill(0));
let loop = Math.floor(n/2);
let mid = Math.floor(n/2);
let count = 1;
let left = 0, right = n-1; // 记录当前圈的最左和最右
// 外循环 控制圈数 内循环 控制四个方向
while(loop--) {
for(let col = left; col <= right; col++) {
res[left][col] = count++;
}
for(let row = left+1; row <= right; row++) {
res[row][right] = count++;
}
for(let col = right-1; col>=left; col--) {
res[right][col] = count++;
}
for(let row = right-1; row >= left+1; row--) {
res[row][left] = count++;
}
left++;
right--;
}
// 奇数,还需要填充res[mid][mid] 位置
if(n%2 == 1) {
res[mid][mid] = count;
}
return res;
};
方法二
var generateMatrix = function(n) {
// let res = Array(n).fill(Array(n).fill(0));
//==》 不能这样创建二维数组,会导致出错
// 会导致创建的二维数组不同行之间的同一列指向同一片数据,一改全改
let res = Array.from(Array(n),()=>Array(n).fill(0));//推荐这样创建二维数组
let count = 1;
let left = 0, top = 0;
let bottom = n-1, right = n-1;
while(left <= right) {
// 行top不变,列从left到right
for(let col = left; col <= right; col++){
res[top][col] = count++;
}
// 列right不变,行从top+1到bottom
for(let row = top+1; row <= bottom; row++) {
res[row][right] = count++;
}
// 行bottom不变,列从right-1到left+1
for(let col = right-1; col >= left; col--) {
res[bottom][col] = count++;
}
// 列left不变,行从bottom-1到top+1
for(let row = bottom-1; row>=top+1; row--){
res[row][left] = count++;
}
left++;
top++;
right--;
bottom--;
}
return res;
};
注意: 不要采用下列形式创建二维数组
错误写法: let res = Array(n).fill(Array(n).fill(0));
使用非for循环直接使用fill 创建二维数组,必须先给一维数组赋初始值,且为基本类型,再赋二维数组,如果直接给 fill 赋值为一个数组,会导致创建的二维数组不同行之间的同一列指向同一片数据,一改全改。
原因在 fill 官方文档里找到一句话:当一个对象被传递给 fill 方法的时候,填充数组的是这个对象的引用。
正确创建二维数组:
let res = Array.from(Array(n),()=>Array(n).fill(0));
相关题目推荐
- 54.螺旋矩阵
- 剑指Offer 29.顺时针打印矩阵