0、基础
(1)异或
相异为1,相同为0。 性质
(2)与
1&1=1,其他都=0。
function swap(arr, i, j){
let temp = arr[i];
arr[i] = arr[j];
arr[j] = arr[i];
}
function swap(arr, i, j){
arr[i] = arr[i]^arr[j];
arr[j] = arr[i]^arr[j];
arr[i] = arr[i]^arr[j];
}
function swap(arr, i, j){
[arr[i], arr[j]] = [arr[j], arr[i]];
}
var singleNumber = function(nums) {
let i = 0;
nums.forEach(n=>{
i ^= n;
});
return i;
};
var singleNumber = function(nums) {
let eor = 0;
nums.forEach(n=>{
eor ^= n;
});
let right = eor & (~eor+1);
let one = 0;
nums.forEach(n=>{
if(n & right){
one ^= n;
}
});
return Array.of(one, eor^one);
};
(3)生成随机数
Math.random()
Math.around(Math.random()*x)
Math.around(Math.random()*9+1)
Math.around(Math.random()*(y-x) + x)
(4)master公式
T(N) = a*T(N/b) + O(N^d)
- log b a < d,时间复杂度为O(N^d)
- log b a > d,时间复杂度为O(N^(log b a))
- log b a = d,是件复杂度为O(N^d * logN)
(5)比较器
function cmp(a, b){
return a.id - b.id;
}
arr.sort(cmp);
1、排序
- 要快选快排;空间少选堆排序;稳定选归并排序。
- sort(),基础类型使用快排,非基础类型使用归并:是为了稳定性。
基于比较的排序
(1)选择排序
- 时间复杂度O(n^2)
- 空间复杂度O(1)
- 不稳定
- 每趟从后面未排序序列中选出一个最小的。
function selectSort(arr){
if(arr === null || arr.length < 2) return;
for(let i = 0; i < arr.length-1; i++){
let minIndex = i;
for(let j = i+1; j < arr.length; j++){
minIndex = arr[j] < arr[minIndex] ? j : minIndex;
}
swap(arr, i, minIndex);
}
}
(2)冒泡排序
- 时间复杂度O(n^2)
- 空间复杂度O(1)
- 稳定
- 从前往后,两两比较,大的往后放,每趟比较后冒出一个最大的元素。
function bubbleSort(arr){
if(arr === null || arr.length < 2) return;
for(let i = arr.length - 1; i > 0; i--){
for(let j = 0; j < i; j++){
if(arr[j] > arr[j+1]){
swap(arr, j, j+1);
}
}
}
}
(3)插入排序
- 时间复杂度最差O(n^2),最佳(n)
- 空间复杂度O(1)
- 稳定
- 将元素从后往前插入已排序序列中,比较直到前一个元素比元素小结束。
function insertSort(arr){
if(arr === null || arr.length < 2) return;
for(let i = 0; i < arr.length-1; i++){
for(let j = i - 1; j > 0 && arr[j] > arr[j+1];j--){
swap(arr, j, j+1);
}
}
}
(4)归并排序
- 时间复杂度O(NlogN)
- 空间复杂度O(N)
- 稳定
- 分成左右两序列,使左右序列分别有序;合并左右序列,小的插入result,指针后移。
function main(arr){
if(arr === null || arr.length < 2) return arr;
process(arr, 0, arr.length-1);
return arr;
}
function process(arr, L, R){
if(L === R) return;
let mid = L + (R-L)>>1;
process(arr, L, mid);
process(arr, mid+1, R);
merge(arr, L, mid, R);
}
function merge(arr, L, M, R){
let result = new Array(R-L+1);
let i = 0;
let p1 = L;
let p2 = M+1;
while(p1 <= M && p2 <= R){
result[i++] = arr[p1] <= arr[p2] ? arr[p1++] : arr[p2++];
}
while(p1 <= M){
result[i++] = arr[p1++];
}
while(p2 <= R){
result[i++] = arr[p2++];
}
for(let i = 0; i < result.length; i++){
arr[L+i] = result[i];
}
}
function smallSum(arr){
if(arr === null || arr.length < 2) return 0;
return process(arr, 0, arr.length-1);
}
function process(arr, l, r){
if(l === r) return 0;
let mid = l + ((r - l)>>1);
return process(arr, 1, mid)
+ process(arr, mid+1, r)
+ merge(arr, 1, mid, r);
}
function merge(arr, l, m, r){
let result = new Array(r-l+1);
let i = 0;
let p1 = l;
let p2 = m+1;
let res = 0;
while(p1 <= m && p2 <= r){
res += arr[p1] < arr[p2] ? (r-p2+1)*arr[p1] : 0;
result[i++] = arr[p1] < arr[p2]? arr[p1++] : arr[p2++];
}
while(p1 <= m){
result[i++] = arr[p1++];
}
while(p2 <= r){
result[i++] = arr[p2++];
}
for(let j = 0; j < result.length; j++){
arr[l+i] = result[i];
}
return res;
}
var reversePairs = function(nums) {
if(nums === null || nums.length < 2) return 0;
return process(nums, 0, nums.length-1);
};
function process(arr, l, r){
if(l === r) return 0;
let mid = l + ((r-l)>>1);
return process(arr, l, mid)
+ process(arr, mid+1, r)
+ merge(arr, l , mid, r);
}
function merge(arr, l, m, r){
let result = new Array(r-l+1);
let i = 0;
let p1 = l;
let p2 = m+1;
let res = 0;
while(p1<=m && p2<=r){
res += arr[p1] > arr[p2] ? r-p2+1 : 0;
result[i++] = arr[p1] > arr[p2]? arr[p1++] : arr[p2++];
}
while(p1<=m){
result[i++] = arr[p1++];
}
while(p2<=r){
result[i++] = arr[p2++];
}
for(let i = 0; i < result.length; i ++){
arr[l+i] = result[i];
}
return res;
}
(5)快速排序
- 时间复杂度O(NlogN)
- 空间复杂度O(logN)
- 不稳定
function divide(arr, num){
let i = -1;
let p = 0;
while(p < arr.length){
if(arr[p] <= num){
swap(arr, i+1, p);
i++;
}
p++;
}
return arr;
}
function dutchNationalFlag(arr, num){
let i = -1;
let j = arr.length;
let p = 0;
while(p < arr.length){
if(arr[p]<num){
swap(arr, i+1, p++);
i++;
}
else if(arr[p]===num){
p++;
}
else if(arr[p]>num){
swap(arr, p, --j);
}
}
}
function quickSortMain(arr){
if(arr === null || arr.length < 2)return;
quickSort(arr, 0, arr.length-1);
}
function quickSort(arr, L, R){
if(L < R){
swap(arr, L + Math.around(Math.random()*(R-L+1)), R);
let p = [...partition(arr, L, R)];
quickSort(arr, L, p[0]-1);
quickSort(arr, p[1]+1, R);
}
}
function partition(arr, L, R){
let i = L-1;
let j = R;
let p = L;
while(p < j){
if(arr[p] < arr[R]){
swap(arr, ++i, p++);
}else if(arr[p] === arr[R]){
p++;
}else if(arr[p] > arr[R]){
swap(arr, p, --j);
}
}
swap(arr, j, R);
return new Array.of(++i, --j);
}
(6)堆排序
- 时间复杂度O(NlogN)
- 空间复杂度O(1)
- 不稳定
- 优先级队列结构就是堆结构。
function heapInsert(arr, index){
while(arr[index] > arr[(index-1)/2]){
swap(arr, index, (index-1)/2);
index = (index - 1) / 2;
}
}
function heapify(arr, index, heapSize){
let lchild = index*2+1;
while(lchild < heapSize){
let bigOne = lchild+1 < heapSize && arr[lchild] < arr[lchild+1]? lchild+1 : lchild;
bigOne = arr[bigOne] > arr[index]? bigOne : index;
if(bigOne === index) break;
swap(arr, bigOne, index);
index = bigOne;
lchild = index*2+1;
}
}
function heapSort(arr){
if(arr === null || arr.length < 2) return;
for(let i = arr.length - 1; i >= 0; i--){
heapify(arr, i, arr.length);
}
let heapSize = arr.length;
swap(arr, 0, --heapSize);
while(heapSize > 0){
heapify(arr, 0, heapSize);
swap(arr, 0, --heapSize);
}
}
function sortedArrDistanceLessK(arr, k){
let heap = new Array();
let index = 0;
for(; index < Math.min(arr.length, k); index++){
heap.push(arr[index]);
heapInsert(heap, index);
}
let i = 0;
for(; index < arr.length; i++, index++){
heap[index] = arr[index];
heapInsert(heap, index);
arr[i] = heap[0];
heap[0] = heap[heap.length-1];
heap.pop();
heapify(heap, 0);
}
while(heap.length>0){
arr[i++] = heap[0];
heap[0] = heap[heap.length-1];
heap.pop();
heapify(heap, 0);
}
}
非基于比较的排序
(1)计数排序
(2)桶排序(基数排序)
function radixSortMain(arr){
if(arr === null || arr.length < 2)return;
radixSort(arr, 0, arr.length - 1, maxbits(arr));
}
function maxbits(arr){
let max = Number.MAX_VALUE;
for(let i = 0; i < arr.length; i++){
max = Math.max(max, arr[i]);
}
let res = 0;
while(max !== 0){
res++;
max /= 10;
}
return res;
}
function radixSort(arr, L, R, digit){
const radix = 10;
let i = 0, j = 0;
let bucket = new Array(R-L+1);
for(let d = 1; d <= digit; d++){
let count = new Array(radix);
for(i = L; i <= R; i++){
j = getDigit(arr[i], d);
count[j]++;
}
for(i = 1; i < radix; i++){
count[i] = count[i] + count[i-1];
}
for(i = R; i >= L; i--){
j = getDigit(arr[i], d);
bucket[count[j]-1] = arr[i];
count[j]--;
}
for(i = L, j = 0; i <= R; i++, j++){
arr[i] = bucket[j];
}
}
}
function getDigit(x, d){
return ((x / (Math.pow(10, d-1)))%10);
}
2、二分查找
有序数组,找某个数是否存在。
有序数组,找>=某个数最左侧的位置。
局部最小值 无序数组,相邻数一定不相等,求局部最小值。
3、哈希表
哈希表
- 增删改查操作的时间复杂度可以认为是O(1),但是常数时间比较大。
- 放入哈希表的东西,如果是基础类型,内部按值传递,内存占用的是这个东西的大小;如果不是基础类型,内部按引用传递,内存占用的是这个东西内存地址的大小。
- JS中的Object
- 有序表
- 有序表和哈希表的区别是,有序表把key按照顺序组织起来,而哈希表完全不组织。
- 放入有序表的东西,如果是基础类型,内部按值传递,内存占用的是这个东西的大小;如果不是基础类型, 必须提供比较器,内部按引用传递,内存占用的是这个东西内存地址的大小。
- 红黑树、AVL树、size-balance-tree和跳表都属于有序表。
- JS中的Map、Set
4、链表
var reserveList = function(head){
let prev = null;
let curr = head;
let next = head;
while(curr !== null){
next = curr.next;
curr.next = prev;
prev = curr;
curr = next;
}
return prev;
};
var reverseList = function(head){
let prev = null;
let curr = head;
while(curr !== null){
[curr.next, prev, curr] = [prev, curr, curr.next];
}
return prev;
};
var reverseList = function(head){
if(head === null || head.next === null){
return head;
}
const last = reserveList(head.next);
head.next.next = head;
head.next = null;
return last;
};
var reserve = function(head){
let prev = null;
let curr = head;
while(curr!==null){
curr.prev = curr.next;
curr.next = prev;
prev = curr;
curr = curr.prev;
}
return prev;
};
var print = function(head1, head2){
let p1 = head1, p2 = head2;
while(p1!==null && p2!==null){
if(p1.data < p2.data){
p1 = p1.next;
}else if(p1.data > p2.data){
p2 = p2.next;
}else{
console.log(p1.data);
p1 = p1.next;
p2 = p2.next;
}
}
}
var partition = function(head, x){
let sH = null;
let sT = null;
let eH = null;
let eT = null;
let bH = null;
let bT = null;
let next = null;
while(head !== null){
next = head.next;
head.next = null;
if(head.val < x){
if(sH === null){
sH = head;
sT = head;
}else{
sT.next = head;
sT = head;
}
}else if(head.val === x){
if(eH === null){
eH = head;
eT = head;
}else{
eT.next = head;
eT = head;
}
}else{
if(bH === null){
bH = head;
bT = head;
}else{
bT.next = head;
bT = head;
}
}
head = next;
}
if(sH !== null){
sT.next = eH;
eT = eT === null? sT : eT;
}
if(eH !== null){
eT.next = bH;
}
return sH !== null ? sH : (eH !== null ? eH : bH);
};
var partition = function(head, x){
let sH = null;
let sT = null;
let eH = null;
let eT = null;
let next = null;
while(head !== null){
next = head.next;
head.next = null;
if(head.val < x){
if(sH === null){
sH = head;
sT = head;
}else{
sT.next = head;
sT = head;
}
}else{
if(eH === null){
eH = head;
eT = head;
}else{
eT.next = head;
eT = head;
}
}
head = next;
}
if(sH !== null){
sT.next = eH;
}
return sH !== null ? sH : eH;
};
var isPalindrome = function(head){
let slow = head;
let fast = head;
while(fast !== null && fast.next !== null){
slow = slow.next;
fast = fast.next.next;
}
if(fast !== null){
slow = slow.next;
}
let left = head;
let right = reverse(slow);
while(right !== null){
if(left.val !== right.val)
return false;
left = left.next;
right = right.next;
}
return true;
};
var reverse = function(head){
let prev = null;
let curr = head;
while(curr !== null){
[curr.next, prev, curr] = [prev, curr, curr.next];
}
return prev;
};
var copyRandomList = function(head){
if(!head) return head;
let map = new Map();
let cur = head;
while(cur !== null){
map.set(cur, new Node(cur.val));
cur = cur.next;
}
cur = head;
while(cur !== null){
map.get(cur).next = map.get(cur.next) || null;
map.get(cur).random = map.get(cur.random) || null;
cur = cur.next;
}
return map.get(head);
}
var copyRandomList = function(head){
if(!head) return head;
let cur = head;
let next = null;
while(cur !== null){
next = cur.next;
cur.next = new Node(cur.val);
cur.next.next = next;
cur = next;
}
cur = head;
let curCopy = null;
while(cur !== null){
next = cur.next.next;
curCopy = cur.next;
curCopy.random = cur.random !== null ? cur.random.next : null;
cur = next;
}
const res = head.next;
cur = head;
while(cur !== null){
next = cur.next.next;
curCopy = cur.next;
cur.next = next;
curCopy.next = next !== null ? next.next : null;
cur = next;
}
return res;
}
|