最近在看数据结构和算法,努力总结出道~前端
指针的本质,是记住数组遍历的进度,从而减小无效遍历的范围。算法
当遍历有序的数组的时候,由于有序,因此更大更小的值已经肯定,能够用指针法记住数组遍历的进度,从而减小无效遍历的范围数组
数组上,单个指针的话,先将指针指向开始(或末尾),而后指针移动,当移动到数组以外,就表示数组遍历完毕。markdown
数组上,两个指针的话,若是出如今两端,随着两边指针移动,未遍历中间的元素范围就慢慢变小,直到指针相邻或者重合表示,遍历完毕,也叫对撞指针法
。数据结构
遇到求和或者比大小问题的时候,若是数组是无序的,能够尝试有序以后再使用指针法。app
我看到的第一想法是sort大法:数据结构和算法
var merge = function (nums1, m, nums2, n) {
// num1里面多余的元素删掉,而且将num2里面的元素插入到num1里面
nums1.splice(m,n,...nums2.slice(0,n))
// 排序
nums1.sort((a,b)=>a-b)
};
复制代码
splice方法必定要会,可删,可增。第一个索引表示要操做的位置(这个位置的元素确定要变),第二个表示删除后面几个,以后的都表示插入的元素。oop
但其实,既然已经有序,就要充分利用这个条件,减小无效遍历。上指针大法!ui
本题,由于是num1够长,由于后面的空间是空的,因此从后面开始利用,节省空间。url
var merge = function (nums1, m, nums2, n) {
// 指针初始都在末尾
let pointer1 = m - 1;
let pointer2 = n - 1;
let fillPointer = m + n - 1;
// 一直遍历,直到有一个数组遍历完,一个数组遍历完的表现就是:pointer1 <0 || pointer2 <0
while (pointer1 >= 0 && pointer2 >= 0) {
// num1指针的指向的值更大的话,就填充此值,而后移动指针,表示此值以后再也不须要遍历了
if (nums1[pointer1] >= nums2[pointer2]) {
nums1[fillPointer] = nums1[pointer1];
pointer1--;
fillPointer--;
} else {
// 同理
nums1[fillPointer] = nums2[pointer2];
pointer2--;
fillPointer--;
}
}
// 当nums1先遍历完的时候,将nums2里面未遍历的值,插入到nums1便可
if (pointer1 < 0) {
// pointer2 >=0是遍历的条件,一旦小于0就表示遍历完了
while (pointer2 >=0) {
nums1[newPointer] = nums2[pointer2];
pointer2--;
newPointer--;
}
}
};
复制代码
显然空间O(1),时间O(m+n)
能够看下官方视频
暴力法,我就不说了,三重遍历,合适的组合丢出来就行,时间复杂度O(n^3)。
显然,这不是想要的过程。
两数求和,用Map,以空间换时间。 但三数求和,不固定的数有两个,是不适合用Map的,这里数组和求和,联想下指针。
指针的前提条件是有序的数组,因此这里先排序,而后使用指针法
var threeSum = function (nums) {
// nums = Array.from(new Set(nums));
nums.sort((a, b) => a - b);
let res = [];
let len = nums.length;
// i是固定的第一个数的指针
for (let i = 0; i < len - 2; i++) {
if (nums[i] > 0) {
break;
}
// 相等就跳过,由于有i-1因此前面必须判断i>0,否则会报错
if (i > 0 && nums[i] === nums[i - 1]) {
continue;
}
// L是左指针
let L = i + 1;
// R是右指针
let R = len - 1;
// 当L>=R的时候,表示数组遍历完了
while (L < R) {
const sum = nums[L] + nums[R] + nums[i];
// 大于0,右指针后退
if (sum > 0) {
// 这句是去重复的。值相同的话,跳过,这里注意必须加L<R,否则R--,是有可能小于L的,这不是咱们想要的
while (L < R && nums[R] === nums[R - 1]) R--;
R--;
} else if (sum < 0) {
while (L < R && nums[L] === nums[L + 1]) L++;
L++;
} else {
res.push([nums[i], nums[L], nums[R]]);
while (L < R && nums[L] === nums[L + 1]) L++;
L++;
while (L < R && nums[R] === nums[R - 1]) R--;
R--;
}
}
}
return res;
};
复制代码
时间复杂度降成O(n^2)。
能够看下官方视频