最近在看數據結構和算法,努力總結出道~前端
指針的本質,是記住數組遍歷的進度,從而減小無效遍歷的範圍。算法
當遍歷有序的數組的時候,由於有序,因此更大更小的值已經肯定,能夠用指針法記住數組遍歷的進度,從而減小無效遍歷的範圍數組
數組上,單個指針的話,先將指針指向開始(或末尾),而後指針移動,當移動到數組以外,就表示數組遍歷完畢。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)。
能夠看下官方視頻