记录一下做算法的历程,之后的算法小编会用javaScript来进行编写,有和我一样是前端的小伙伴同时也想提高自己的算法能力的可以一起学习。
第一周我想尝试一些双指针类型的题目。
在这周的算法学习中,js数组的删除方法用到的比较多。
- splice(index,len,[item]) 可以用来替换/删除/添加数组内某一个或者几个值。
- 替换:替换起始下标为index,长度为len的一个值item
var arr = ['a','b','c','d'] arr.splice(1,2,'item') // ['a','item','d']
- 删除:删除起始下标为index,长度为len的一个值
var arr = ['a','b','c','d'] arr.splice(1,2) // ['a','d']
- 添加:len设置为0,item为添加的值
var arr = ['a','b','c','d'] arr.splice(1,0,'item') // ['a','item','b','c','d']
- 三数之和(排序加双指针)
/**
* @param {number[]} nums
* @return {number[][]}
*/
function compare(a,b) {
return a-b;
}
var threeSum = function(nums) {
let res=[]
let len=nums.length
if(nums == null || len < 3) return res;
//先对数组进行排序
nums.sort(compare)
for(let i=0;i<len;i++){
// 如果大于0则之后相加不可能等于0
if(nums[i] > 0) break
if(i > 0 && nums[i] == nums[i-1]) continue;
let L=i+1;
let R=len-1;
while(L<R){
let sum=nums[i]+nums[L]+nums[R]
if(sum==0){
res.push([nums[i],nums[L],nums[R]])
while(L<R&&nums[L]==nums[L+1]) L++ //判断是否重复
while(L<R&&nums[R]==nums[R-1]) R--
L++
R--
}else if(sum<0){
L++
}else if(sum>0){
R--
}
}
}
return res
};
console.log(threeSum([-1, 0, 1, 2, -1, -4]))
console.log(threeSum([-1, 0, 1, 2, -1, 2]))
console.log(threeSum([0,0,0,0]))
console.log(threeSum([1,1,-2]))
console.log(threeSum([1,1,0]))
console.log(threeSum([0,0,0]))
console.log(threeSum([-2,0,1,1,2]))
/**
* @param {number[]} nums
* @return {number}
*/
var removeDuplicates = function(nums) {
let L=0;
let R=L+1;
while(R<=nums.length){
if(nums[L]==nums[R]){
nums.splice(R,1)
}else{
L++
R++
}
}
return nums.length;
};
/**
* @param {number[]} nums
* @return {number}
*/
var removeDuplicates = function(nums) {
let L=0;
let R=L+2;
while(R<=nums.length){
if(nums[L]==nums[R]){
nums.splice(R,1)
}else{
L++;
R++;
}
}
return nums.length
};
4.移动零
/**
* @param {number[]} nums
* @return {void} Do not return anything, modify nums in-place instead.
*/
var moveZeroes = function(nums) {
let L=0
let R=1
//这里必须为nums.length-1,否则会陷入死循环,因为num[nums.length+1]!=0是undefined
while(R<=nums.length-1){
//如果第L个是非零数字,则两个指针同时向前
if(nums[L]!=0){
L++
R++
}
else if(R<=nums.length&&nums[L]==0 && nums[R]!=0){
nums[L]=nums[R]
nums[R]=0
L++
R++
}
else if(nums[L]==0 && nums[R]==0){
while(R<=nums.length-1 && nums[R]==0){
R++;
}
}
}
return nums
};
5.最接近的三数之和
/**
* @param {number[]} nums
* @param {number} target
* @return {number}
*/
var threeSumClosest = function(nums, target) {
let len=nums.length
let res=[]
let index=0
if(len<3) return res[0]
if(len==3) return nums[0]+nums[1]+nums[2]
for(let i=0;i<len;i++){
let L=i+1
let R=L+1
while(L<len){
while(R<len){
res[index]=nums[i]+nums[L]+nums[R]
R++
index++
}
L++
R=L+1
}
}
let resNum=[]
for(let i=0;i<index;i++){
// console.log(index,res[i])
resNum[i]=Math.abs(res[i]-target)
// console.log(resNum[i])
}
let min = resNum[0]
let resMin=res[0]
for(let i=0;i<index;i++){
if(min>resNum[i]){
min=resNum[i]
resMin=res[i]
}
}
return resMin;
};
- 上面的这个代码时间复杂度太高,优化代码为以下:
- 与上面第一题的思路一样都是:
- 现将数组从小到大排序,从左到右先固定一个数,头尾双指针进行扫描
- 如果sum大于target,就左移右指针,否则右移左指针
- 在看sum-target的绝对值是否比之前的更小了,如果是,更新
/**
* @param {number[]} nums
* @param {number} target
* @return {number}
*/
var threeSumClosest = function(nums, target) {
//排序
let numsSort = nums.sort((a,b)=>{return a-b})
let len=nums.length
if(len==3) return nums[0]+nums[1]+nums[2]
let sum
let cha=1000
let res
for(let i=0;i<len;i++){
let L=i+1
let R=len-1
while(L<R){
sum=numsSort[i]+numsSort[L]+numsSort[R]
if(Math.abs(sum-target)<cha){
res=sum
cha=Math.abs(sum-target)
}
if(sum<target){
L++
}
if(sum>target){
R--
}
if(cha==0){
return sum
}
}
}
return res
};
6.子集
- 循环nums,每次添加一个nums[i],每添加一个nums[i],就与res数组中前面的所有元素组成一个新的数组(例如,添加[1],[2],当添加元素[2]时,循环res数组,将元素[2]与res数组前面的元素组合)
/**
* @param {number[]} nums
* @return {number[][]}
*/
var subsets = function(nums) {
let res = []
let arr1=[]
let num=0
for(let i=0;i<nums.length;i++){
arr1=[nums[i]]
res.push(arr1)
num=0
let len=res.length
for(let j=0;j<res.length;j++){
if(!res[j].includes(nums[i])){
let arr=[].concat(res[j])
arr.push(nums[i])
res.push(arr)
num++
}
if(num-1==len){
break;
}
}
}
res.unshift([])
return res
};