1.二分查找
给定一个 n 个元素有序的(升序)整型数组 nums 和一个目标值 target ,写一个函数搜索 nums 中的 target,如果目标值存在返回下标,否则返回 -1。
示例 1:
输入: nums = [-1,0,3,5,9,12], target = 9 输出: 4 解释: 9 出现在 nums 中并且下标为 4
使用普通的遍历
var search = function(nums, target) {
for(var i=0;i<nums.length;i++){
if(nums[i]==target){
return i
}
}
return -1
};
使用二分查找
// 二分查找
var serach = function (nums, target) {
let left = 0;
let right = nums.length;
let mid = Math.ceil((left + right) / 2);
console.log(mid);
while (left < right) {
if (nums[mid] > target) {
right = mid - 1;
} else if (nums[mid] < target) {
left = mid + 1;
} else {
return mid;
}
}
return -1;
};
serach(nums, target);
console.log(serach(nums, target));
2.移除元素
给你一个数组 nums 和一个值 val,你需要 原地 移除所有数值等于 val 的元素,并返回移除后数组的新长度。
不要使用额外的数组空间,你必须仅使用 O(1) 额外空间并原地修改输入数组。
元素的顺序可以改变。你不需要考虑数组中超出新长度后面的元素。
示例 1: 给定 nums = [3,2,2,3], val = 3, 函数应该返回新的长度 2, 并且 nums 中的前两个元素均为 2。 你不需要考虑数组中超出新长度后面的元素。
方法一:使用新的数组来存储
var nums = [2, 3, 4, 2];
var val = 2;
// 移除元素
var dele = function (nums, val) {
let arr = [];
for (let i = 0; i < nums.length; i++) {
if (nums[i] !== val) {
arr.push(nums[i]);
}
}
return arr.length;
};
console.log(dele(nums, val));
方法二:双重循环
// 方法二:双重遍历
var dele = function (nums, val) {
for (let i = 0; i < nums.length; i++) {
if (nums[i] == val) {
//发现需要移除的元素,就将数组集体向前移动一位
//num[0]=2
for (let j = i + 1; j < nums.length; j++) {
nums[j - 1] = nums[j]; //nums[0]=3,nums[1]=4,nums[2]=2
}
i--; // 因为下标i以后的数值都向前移动了一位,所以i也向前移动一位
nums.length--; // 此时数组的大小-1
}
}
return nums.length;
};
console.log(dele(nums, val));
3.有序数组的平方
给你一个按 非递减顺序 排序的整数数组 nums,返回 每个数字的平方 组成的新数组,要求也按 非递减顺序 排序。
示例 1: 输入:nums = [-4,-1,0,3,10] 输出:[0,1,9,16,100] 解释:平方后,数组变为 [16,1,0,9,100],排序后,数组变为 [0,1,9,16,100]
暴力排序
最直观的想法,莫过于:每个数平方之后,排个序
var nums = [2, 3, 4];
var sortarr = function (nums) {
let arr = [];
for (let i = 0; i < nums.length; i++) {
arr.push(nums[i] * nums[i]);
}
arr.sort((a, b) => {
return a - b;
});
return arr;
};
console.log(sortarr(nums));
双指针法
数组其实是有序的, 只不过负数平方之后可能成为最大数了。
那么数组平方的最大值就在数组的两端,不是最左边就是最右边,不可能是中间。
var sortarr = function (nums) {
let n = nums.length;
//创建一个数组并填充对应的数 [0, 0, 0, 0, 0, 0, 0, 0]
let temp = new Array(n).fill(0);
let left = 0;
let right = n - 1;
let k = n - 1;
while (left <= right) {
if (nums[left] * nums[left] > nums[right] * nums[right]) {
temp[k] = nums[left] * nums[left];
k--;
left++;
} else {
temp[k] = nums[right] * nums[right];
k--;
right--;
}
}
return temp;
};
console.log(sortarr(nums));
4.长度最小的子数组
给定一个含有 n 个正整数的数组和一个正整数 target 。
找出该数组中满足其和 ≥ target 的长度最小的 连续子数组 [numsl, numsl+1, ..., numsr-1, numsr] 并返回其长度。如果不存在符合条件的子数组,返回 0 。
方法一:暴力解法
时间复杂度: O (n2) 空间复杂度 :O(1)
思路:用i 和 j 表示子数组的头序号和尾序号,
用rl表示最小连续子数组长度,初始值为原数组长度
sum储存子数组内数组和
sumlength子数组长度
var nums = [2, 3, 1, 2, 4, 3];
var target = 7;
var minarr = function (nums, target) {
let r = 0;
let l = 0;
let sumlength = nums.length;
let sum;
let rl = 0;
for (let i = 0; i < nums.length; i++) {
sum = 0; //初始化,开始踢掉头一个数,重新找最小子数组
for (let j = i; j < nums.length; j++) {
sum += sum[j];
rl = j - i + 1;
if (sum >= target) {
sumlength = sumlength > rl ? rl : sumlength;
}
}
}
return sumlength > rl ? 0 : sumlength;
};
方法二:双指针法
var minarr = function (nums, target) {
let r = 0;
let l = 0;
let sumlength = nums.length;
let sum = 0;
let rl = 0;
// 遍历整个数组
while (r < nums.length) {
sum += nums[r++]; //小于目标值,移动指针,累加sum
while (sum >= target) {
rl = r - l; // r-l就是队列中元素的长度
sumlength = sumlength > rl ? rl : sumlength;
sum -= nums[l++]; // 用l指针控制弹出队头的元素
}
}
return sumlength > rl ? 0 : sumlength;
};
console.log(minarr(nums, target));