Algorithm
Table of Contents
- 1. Bubble
- 2. Select
- 3. Insert
- 4. merge
- 5. quick
- 6. heap
- 7. Shell Sort
- 8. Redix
- 9. Bucket Sort
- 10. Count Sort
- 11. Dichotomy
- 12. Stupidmax
- 13. HoffmannCode
- 14. JosephusRing
- 15. KMPmachting
- 16. Longest Substring Without Repeating Characters
- 17. k-way Merge
- 18. Dynamic program
- 19. Maximum subarray
- 20. maximum submatrix
- 21. Find the sum of a specific value in a list
- 22. Langest increasing subsequence (LIS)
- 23. packsack
- 24. Order Statistics
- 25. Range Minimun Query
- 26. Computional Geometry
- 27. Master Theorem
- 27.1. 1 \(T(n) = 3T(n/2) + n^{2}\)
- 27.2. 2 \(T(n) = 4T(n/2) + n^{2}\)
- 27.3. 3 \(T(n) = T(n/2) + 2^{n}\)
- 27.4. 4 \(T(n) = 2^{n}T(n/2) + n^{n}\)
- 27.5. 5 \(T(n) = 16T(n/4) + n\)
- 27.6. 6 \(T(n) = 2T(n/2) + nlogn\)
- 27.7. 7 \(2T(n) = 2T(n/2) + n/logn\)
- 27.8. 8 \(T(n) = 2T(n/4) + n^{0.51}\)
- 27.9. 9 \(T(n) = 0.5T(n/2) +1/n\)
- 27.10. 10 \(T(n) = 16T(n/4) + n!\)
- 27.11. 11 \(T(n) = \sqrt{2} T(n/2) + logn\)
- 27.12. 12 \(T(n) = 3T(n/2) +n\)
- 27.13. 13 \(T(n) = 3T(n/3) +\sqrt{n}\)
- 27.14. 14 \(T(n) = 4T(n/2) + cn\)
- 27.15. 15 \(T(n) = 3T(n/4) + nlogn\)
- 27.16. 16 \(T(n) = 3T(n/3) + n/2\)
- 27.17. 17 \(T(n) = 6T(n/3) +n^{2}logn\)
- 27.18. 18 \(T(n) = 4T(n/2) + n/logn\)
- 27.19. 19 \(T(n) = 64T(n/8) -n^{2}logn\)
- 27.20. 20 \(T(n) = 7T(n/3) + n^{2}\)
- 27.21. 21 \(T(n) = 4T(n/2) + logn\)
- 27.22. 22 \(T(n) = T(n/2) + n(2-cosn)\)
- 28. Universal Hashing
- 29. From binary Heap to Fibonacci Heap
1. Bubble
1.1. Algorithm
each time compare itself with the next, if smaller, exchange them after each epoch, the biggest will be right localed. with the cursor moving, always with the so far biggest
A[a] for a -> 0, 1, 2, 3....l
FOR i -> 0, 1, 2...l-2:
FOR j -> 0, 1, 2...l-2-i:
IF A[j] > A[j+1]:
exchange A[j]:A[j+1]
1.2. Python
A = [2,5,6,8,45,68,98,42,12,7,156,158,9]
lang = len(A)
for i in range(lang-2):
for j in range(lang-i-1):
if A[j] > A[j+1]:
A[j], A[j+1] = A[j+1], A[j]
print(A)
[2, 5, 6, 7, 8, 9, 12, 42, 45, 68, 98, 156, 158]
1.3. java
class BubbleSorting
{
public static void main(String[] args)
{
int A[] = {2,5,6,8,45,68,98,42,12,7,156,158,9};
int langdu = A.length;
for (int i = 0; i <= langdu-2; i++) {
for (int j = 0; j <= langdu-2-i; j++) {
if (A[j] > A[j+1]) {
int tmp = A[j+1];
A[j+1] = A[j];
A[j] = tmp;
}
}
}
for (int a:A){
System.out.printf("%d ", a);
}
}
}
2 5 6 7 8 9 12 42 45 68 98 156 158
1.4. C/C++
int main(int argc, char *argv[])
{
int list[] = {2,5,6,8,45,68,98,42,12,7,156,158,9};
int langdu = sizeof(list) / sizeof(int);
void swap(int *a, int *b){
int tmp = *b;
*b = *a;
*a = tmp;
}
for (int i = 0; i <= langdu-2; ++i) {
for ( int j=0; j <= langdu-2-i;++j) {
if (list[j] > list[j+1]) {
swap(&list[j], &list[j+1]);
}
}
};
for (int k = 0; k < langdu; ++k) {
printf("%d ",*(list+k));
}
return 0;
}
2 5 6 7 8 9 12 42 45 68 98 156 158
2. Select
2.1. Algorithm
find the sofar biggest or smallest one of each epoch at the front of list, after each epoch put it to the right place.
A[a] for a -> 0, 1, 2....l
FOR i -> 0, 1, 2...l-1:
FOR j -> 0, 1, 2....l-1-i:
IF A[j] > A[0]:
exchange(A[j], A[0])
exchange(A[0], A[l-1-i])
2.2. Python
A = [2,5,6,8,45,68,98,42,12,7,156,158,9]
lang = len(A)
for i in range(lang):
for j in range(lang-i):
if A[j] > A[0]:
A[j], A[0] = A[0], A[j]
A[0], A[lang-1-i] = A[lang-1-i], A[0]
print(A)
[2, 5, 6, 7, 8, 9, 12, 42, 45, 68, 98, 156, 158]
2.3. Java
class SelectSorting
{
public static void main(String[] args)
{
int A[] = {2,5,6,8,45,68,98,42,12,7,156,158,9};
int langdu = A.length;
for (int i = 0; i <= langdu-1; i++) {
for (int j = 0; j <= langdu-1-i; j++) {
if (A[j] > A[0]) {
int tmp = A[j];
A[j] = A[0];
A[0] = tmp;
}
}
int tmp = A[langdu-1-i];
A[langdu-1-i] = A[0];
A[0] = tmp;
}
for (int var : A) {
System.out.printf("%d ", var);
}
}
}
2 5 6 7 8 9 12 42 45 68 98 156 158
2.4. C/C++
int main(int argc, char *argv[])
{
int list[] = {2,5,6,8,45,68,98,42,12,7,156,158,9};
int langdu = sizeof(list) / sizeof(int);
int i, j;
void swap(int *a, int *b){
int tmp = *b;
*b = *a;
*a = tmp;
}
for (i = 0; i <= langdu -1; ++i) {
for (j = 0; j <= langdu-1-i; ++j) {
if (list[j] > list[0]) {
swap(&list[j], &list[0]);
}
}
swap(&list[0], &list[langdu-1-i]);
}
for (int k = 0; k < langdu; ++k) {
printf("%d ",*(list+k));
}
return 0;
}
2 5 6 7 8 9 12 42 45 68 98 156 158
3. Insert
3.1. Algorithm
A[a] for a -> 0, 1, 2....l-1
for i -> 1, 2...l-1:
value <- A[i]
index <- i
while(A[index-1] > value && index > 0)
A[index] = A[index-1]
index--
A[index] <- value
3.2. Python
list1 = [2, 1, 3, 4, 5, 3, 6, 7, 8, 4, 9, 45, 9,34, 23,345, 546,20, 23465, 90, 19]
langdu = len(list1)
for i in range(1, langdu):
value = list1[i]
index = i
while(index > 0 and list1[index-1] > value):
list1[index] = list1[index-1]
index -= 1
list1[index] = value
print(list1)
[1, 2, 3, 3, 4, 4, 5, 6, 7, 8, 9, 9, 19, 20, 23, 34, 45, 90, 345, 546, 23465]
3.3. Java
class Inserting
{
public static void main(String[] args)
{
int list1 [] = {2, 1, 3, 4, 5, 3, 6, 7, 8, 4, 9, 45, 9,34, 23,345, 546,20, 23465, 90, 19};
int langdu = list1.length;
for (int i = 1; i < langdu; i++) {
int value = list1[i];
int index = i;
while(index > 0 && list1[index-1] > value) {
list1[index] = list1[index-1];
index--;
}
list1[index] = value;
}
for (int var :list1) {
System.out.printf("%d ", var);
}
}
}
1 2 3 3 4 4 5 6 7 8 9 9 19 20 23 34 45 90 345 546 23465
3.4. C/C++
int main(int argc, char *argv[])
{
int A[] = {2, 1, 3, 4, 5, 3, 6, 7, 8, 4, 9, 45, 9,34, 23,345, 546,20, 23465, 90, 19};
int langdu = sizeof(A)/sizeof(int);
for (int i = 1; i < langdu; ++i) {
int value = A[i];
int index = i;
while (index > 0 && A[index-1] > value) {
A[index] = A[index-1];
index--;
}
A[index] = value;
}
for (int i = 0; i < langdu; ++i) {
printf("%d ",A[i] );
}
return 0;
}
1 2 3 3 4 4 5 6 7 8 9 9 19 20 23 34 45 90 345 546 23465
int main(int argc, char *argv[])
{
int A[] = {2, 1, 3, 4, 5, 3, 6, 7, 8, 4, 9, 45, 9,34, 23,345, 546,20, 23465, 90, 19};
int langdu = sizeof(A)/sizeof(int);
insert(A, langdu);
for (int i = 0; i < langdu; ++i) {
printf("%d ",A[i] );
}
return 0;
}
void insert(int A[], int langdu){
for (int i = 1; i < langdu; ++i) {
int value = A[i];
int index = i;
while (index > 0 && A[index-1] > value) {
A[index] = A[index-1];
index--;
}
A[index] = value;
}
return;
}
1 2 3 3 4 4 5 6 7 8 9 9 19 20 23 34 45 90 345 546 23465
4. merge
4.1. Algorithm
A[a] for a -> 0, 1, 2.....l-1
ll = 0
rr = l-1
mergersort(A, ll, rr)
mergersort(A, ll, rr)
solang ll < rr
dd = (ll+rr)/2
A1[a] for a-> ll...dd
A2[a] for a -> dd+1..rr
mergersort(A1, ll, dd)
mergersort(A2, dd+1, rr)
merge(A1, ll, dd, A2, dd+1, rr)
else return
merge(A1, A2)
A1[i] for i -> 0...I
A2[j] for j -> 0...J
C[k] for k -> 0....I+J
if A1[i] > A2[j] && i < I && j < J
C[k] <- A2[j]
k++
j++
if i < I
C[k...k+(I-i)] <- A1[i...I]
if J < J
C[k...k+(J-j)] <- A2[j...J]
A[a] for a -> 0, 1, 2....l-1
mergersort(A)
mergersort(A):
if len(A) > 1:
A1, A2 <- A
A1 = mergersort(A1)
A2 = mergersort(A2)
return merge(A1, A2)
else return A
merge(A1, A2):
A1[i] for i -> 0...I
A2[j] for j -> 0...J
C[k] for k -> 0...I+J
while i < I and j < J:
if A1[i] > A2[j]:
C[k] <- A2[j]
j++
else C[k] <- A1[i]
i++
k++
while i <= I
C[k] <- A1[i]
while j <= J
C[k] <- A2[j]
return C
4.2. Python
def mergesort(list1):
if len(list1) <= 1:
return list1
mid = int(len(list1)/2)
lista = list1[:mid]
listb = list1[mid:]
lista = mergesort(lista)
listb = mergesort(listb)
return merge(lista, listb)
def merge(lista, listb):
result = []
i = 0
j = 0
while(i < len(lista) and j < len(listb)):
if lista[i] > listb[j]:
result.append(listb[j])
j += 1
else:
result.append(lista[i])
i += 1
result += lista[i:]
result += listb[j:]
return result
list1 = [2, 1, 3, 4, 5, 3, 6, 7, 8, 4, 9, 45, 9,34, 23,345, 546,20, 23465, 90, 19]
langdu = len(list1)
list1 = mergesort(list1)
print(list1)
[1, 2, 3, 3, 4, 4, 5, 6, 7, 8, 9, 9, 19, 20, 23, 34, 45, 90, 345, 546, 23465]
4.3. Java
mit index augenment
import java.util.*;
class Merging
{
public static void main(String[] args)
{
int a [] = {2, 1, 3, 4, 5, 3, 6, 7, 8, 4, 9, 45, 9,34, 23,345, 546,20, 23465, 90, 19};
int langdu = a.length-1;
mergsort(a, 0, langdu );
for(int var : a){
System.out.printf("%d ", var);
}
}
private static void mergsort(int [] a, int lo, int hi){
if (lo >= hi) {
return;
}
int mid = lo + (hi-lo)/2;
mergsort(a, lo, mid);
mergsort(a, mid+1, hi);
merge(a, lo, mid, hi);
}
private static void merge(int [] a, int lo, int mid, int hi){
int [] news = new int [hi-lo+1];
int p = lo;
int q = mid+1;
int index = 0;
while(p <= mid && q <= hi){
if (a[p] > a[q]) {
news[index++] = a[q++];
}else{
news[index++] = a[p++];
}
}
while(p <= mid){
news[index++] = a[p++];
}
while(q <= hi){
news[index++] = a[q++];
}
System.arraycopy(news, 0, a, lo, hi-lo+1);
}
}
1 2 3 3 4 4 5 6 7 8 9 9 19 20 23 34 45 90 345 546 23465
without index augenment
import java.util.*;
class Merginge
{
public static void main(String[] args)
{
int a [] = {2, 1, 3, 4, 5, 9, 7, 8, 6, 10, 2, 1, 3, 4, 5, 3, 6, 7, 8, 4, 9, 45, 9,34, 23,345, 546,20, 23465, 90, 19};
int [] result = mergsort(a);
for(int var : result){
System.out.printf("%d ", var);
}
}
private static int [] mergsort(int [] a){
if (a.length <= 1) {
return a;
}
int mid = a.length/2;
int [] left = new int [mid];
int [] right = new int [a.length - mid];
for (int i = 0; i < mid; i++) {
left[i] = a[i];
}
for (int i = mid; i < a.length; i++) {
right[i-mid] = a[i];
}
left = mergsort(left);
right = mergsort(right);
return merge(left, right);
}
private static int[] merge(int [] left, int [] right){
int lenleft = left.length-1;
int leftindex = 0;
int lenright = right.length-1;
int rightindex = 0;
int [] result = new int[lenleft+lenright+2];
int index = 0;
while(leftindex <= lenleft && rightindex <= lenright){
if (left[leftindex] > right[rightindex]) {
result[index++] = right[rightindex++];
}else{
result[index++] = left[leftindex++];
}
}
while(leftindex <= lenleft){
result[index++] = left[leftindex++];
}
while(rightindex <= lenright){
result[index++] = right[rightindex++];
}
return result;
}
}
1 1 2 2 3 3 3 4 4 4 5 5 6 6 7 7 8 8 9 9 9 10 19 20 23 34 45 90 345 546 23465
4.4. C/C++
#include <stdio.h>
#include <stdlib.h>
#define N 7
void merge(int arr[], int low, int mid, int high){
int i, k;
int *tmp = (int *)malloc((high-low+1)*sizeof(int));
int left_low = low;
int left_high = mid;
int right_low = mid + 1;
int right_high = high;
for(k=0; left_low<=left_high && right_low<=right_high; k++){
if(arr[left_low]<=arr[right_low]){
tmp[k] = arr[left_low++];
}else{
tmp[k] = arr[right_low++];
}
}
if(left_low <= left_high){
for(i=left_low;i<=left_high;i++)
tmp[k++] = arr[i];
}
if(right_low <= right_high){
for(i=right_low; i<=right_high; i++)
tmp[k++] = arr[i];
}
for(i=0; i<high-low+1; i++)
arr[low+i] = tmp[i];
free(tmp);
return;
}
void merge_sort(int arr[], unsigned int first, unsigned int last){
int mid = 0;
if(first<last){
mid = (first+last)/2; /* 注意防止溢出 */
merge_sort(arr, first, mid);
merge_sort(arr, mid+1,last);
merge(arr,first,mid,last);
}
return;
}
int main(){
int i;
int a[N]={32,12,56,78,76,45,36};
printf ("排序前 \n");
for(i=0;i<N;i++)
printf("%d\t",a[i]);
merge_sort(a,0,N-1); // 排序
printf ("\n 排序后 \n");
for(i=0;i<N;i++)
printf("%d\t",a[i]); printf("\n");
system("pause");
return 0;
}
排序前 32 12 56 78 76 45 36 排序后 12 32 36 45 56 76 78
5. quick
5.1. Algorithm
A[a] for a -> 0, 1, 2...l-1:
quicksort(A, 0, l-1)
quicksort(A, start, end):
if start >= end:
return;
else:
pivot = A[start]
int i = start
int j = end
while(i != j):
whil (j > i && A[j] > pivot):
j--
exchange(A[i], A[j])
while(i < j && A[i] < pivot):
i++
exchange(A[i], A[j])
quicksort(A, start, i+1)
quicksort(A, i+1, end)
5.2. Python
def quicksort(A, start, end):
if start >= end:
return
pivot = A[start]
i = start
j = end
while i != j:
while j > i and A[j] >= pivot:
j -= 1
A[i], A[j] = A[j], A[i]
while i < j and A[i] <= pivot:
i += 1
A[i], A[j] = A[j], A[i]
quicksort(A, start, j-1)
quicksort(A, i+1, end)
return
list1 = [2, 1, 3, 4, 5, 3, 5, 7, 8, 45, 9, 25,
34, 23, 345, 546, 20, 23465, 90, 19]
langdu = len(list1)
quicksort(list1, 0, langdu-1)
print(list1)
[1, 2, 3, 3, 4, 5, 5, 7, 8, 9, 19, 20, 23, 25, 34, 45, 90, 345, 546, 23465]
5.3. Java
class Quicking
{
public static void main(String[] args)
{
int a [] = {2, 1, 3, 4, 5,9087, 3, 6, 7, 8, 4, 9, 45, 9,34, 23,345, 546,20, 23465, 90, 19};
int langdu = a.length-1;
quicksort(a, 0, langdu);
for (int var: a) {
System.out.printf("%d ", var);
}
}
private static void quicksort(int [] a, int start, int end ){
if (start >= end) {
return;
}
int pivot = a[start];
int i = start;
int j = end;
while(i != j){
while(j > i && a[j] >= pivot){
j--;
}
int tmp = a[j];
a[j] = a[i];
a[i] = tmp;
while(i < j && a[i] <= pivot){
i++;
}
tmp = a[j];
a[j] = a[i];
a[i] = tmp;
}
quicksort(a, start, i-1);
quicksort(a, i+1, end);
}
}
1 2 3 3 4 4 5 6 7 8 9 9 19 20 23 34 45 90 345 546 9087 23465
5.4. C/C++
void swap(int *a, int *b){
int tmp = *b;
*b = *a;
*a = tmp;
}
void quicksort(int a[], int start, int end){
if (start >= end) {
return;
}
int pivot = a[start];
int i = start;
int j = end;
while (i != j) {
while (j > i && a[j] > pivot)
j--;
swap(&a[i], &a[j]);
while (i < j && a[i] < pivot)
i++;
swap(&a[i], &a[j]);
quicksort(a, start, i-1);
quicksort(a, i+1, end);
return;
}
}
int main(int argc, char *argv[])
{
int A[] = {2, 1, 3, 4, 5, 3, 6, 7, 8, 4, 9, 45, 9,34, 23,345, 546,20, 23465, 90, 190};
int langdu = sizeof(A)/sizeof(int);
quicksort(A, 0, langdu-1);
for (int i = 0; i < langdu; ++i) {
printf("%d ", A[i]);
}
return 0;
}
1 2 3 4 3 4 5 6 7 8 9 9 20 23 34 45 190 345 546 90 23465
6. heap
6.1. Algorithm
| buildheap() | build all the data to heap |
| heapify(list, n, i) | from i on, can only grante that, the frist is the biggest |
at frist build the heap, and then each time take the biggest one n:length, i the startup
heapify(list, n, i){
leftchild = 2i+1
rightchild = 2i+2
maxindex = i
if leftchild < n && list[leftchild] > list[maxindex]:
maxindex = leftchild
if rightchild < n && list[rightchild] > list[maxindex]:
maxindex = rightchild
if maxindex != i:
exchange(list[maxindex], list[i])
heapify(list, n, maxindex)
}
build_heap(list, n){
last_parent = (n-1)/2
for i -> last_parent....0:
heapify(list, n, i)
}
build_heap(list, n)
for i -> n-1....0:
swap(list, i, 0)
heapify(list, i, 0)
6.2. python
def heapify(list1, n, i):
leftchild = 2*i+1
rightchild = 2*i +2
maxindex = i
if leftchild < n and list1[leftchild] > list1[maxindex]:
maxindex = leftchild
if rightchild < n and list1[rightchild] > list1[maxindex]:
maxindex = rightchild
if maxindex != i:
list1[maxindex], list1[i] = list1[i], list1[maxindex]
heapify(list1, n, maxindex)
def heap_build(list1, n):
last_parent = (n-1)//2
for i in range(last_parent+1):
j = last_parent-i
heapify(list1, n, j)
list1 = [2, 1, 3, 4, 5, 3, 5, 7, 8, 45, 9, 25, 34, 23, 345, 546, 20, 23465, 90, 19]
langdu = len(list1)
heap_build(list1, langdu)
print(list1)
for i in range(langdu):
j = langdu-1-i
list1[0], list1[j] = list1[j], list1[0]
heapify(list1, j, 0)
print(list1)
[23465, 546, 345, 90, 45, 34, 23, 20, 8, 19, 9, 25, 3, 3, 5, 7, 1, 2, 4, 5] [1, 2, 3, 3, 4, 5, 5, 7, 8, 9, 19, 20, 23, 25, 34, 45, 90, 345, 546, 23465]
6.3. Java
class HeapSorting
{
public static void main(String[] args)
{
int a [] = {2, 1, 3, 4, 5,9087, 3, 6, 7, 8, 4, 9, 45, 9,34, 23,345, 546,20, 23465, 90, 190};
int langdu = a.length;
build_heap(a, langdu);
for (int i = langdu-1; i >= 0; i--) {
int tmp = a[0];
a[0] = a[i];
a[i] = tmp;
heapify(a, i, 0);
}
for (int i = 0; i < langdu; i++) {
System.out.printf("%d ", a[i]);
}
}
private static void heapify(int a[], int n, int i){
int leftchild = i*2+1;
int rightchild = i*2+2;
int maxindex = i;
if (leftchild < n && a[leftchild] > a[maxindex] ) {
maxindex = leftchild;
}
if (rightchild < n && a[rightchild] > a[maxindex]) {
maxindex = rightchild;
}
if (maxindex != i) {
int tmp = a[maxindex];
a[maxindex] = a[i];
a[i] = tmp;
heapify(a, n, maxindex);
}
}
private static void build_heap(int a[], int n){
int last_parent = (n-1-1)/2;
for (int i = last_parent; i >= 0; i--) {
heapify(a, n, i);
}
}
}
1 2 3 3 4 4 5 6 7 8 9 9 20 23 34 45 90 190 345 546 9087 23465
6.4. C/C++
void swap(int *a, int *b){
int tmp = *a;
*a = *b;
*b = tmp;
}
void heapify(int A[], int N, int i){
int leftchild = i*2+1;
int rightchild = i*2+2;
int maxindex = i;
if (leftchild < N && A[leftchild] > A[maxindex]) {
maxindex = leftchild;
}
if (rightchild < N && A[rightchild] > A[maxindex]) {
maxindex = rightchild;
}
if (maxindex != i) {
swap(&A[maxindex], &A[i]);
heapify(A, N, maxindex);
}
}
void build_heap(int A[], int N){
int last_parent = (N-1-1)/2;
int i;
for (i = last_parent; i >= 0; i--) {
heapify(A, N, i);
}
}
int main(int argc, char *argv[])
{
int A[] = {2, 1, 3, 4, 5, 3, 6, 7, 8, 4, 9, 45, 9,34, 23,345, 546,20, 23465, 90, 190};
int N = sizeof(A)/sizeof(int);
build_heap(A, N);
for (int i = N-1; i >= 0; i--) {
swap(&A[i], &A[0]);
heapify(A, i, 0);
}
for (int j = 0; j < N; ++j) {
printf("%d ",A[j]);
}
return 0;
}
1 2 3 3 4 4 5 6 7 8 9 9 20 23 34 45 90 190 345 546 23465
6.5. Typescript
swap in-place
// let swap = function (left:number, right:number){
// var temp = left
// left = right
// right = temp
// }
let heapfly = function(list:number[], length:number, index:number){
var leftchild = index*2+1
var rightchild = index*2+2
var maxindex = index
if (leftchild < length && list[leftchild] >list[maxindex]) {
let temp = leftchild
leftchild = maxindex
maxindex = temp
// swap(leftchild, minindex)
}
if (rightchild < length && list[rightchild]>list[maxindex]) {
let tmp = rightchild
rightchild = maxindex
maxindex = tmp
// swap(leftchild, minindex)
}
if (maxindex != index) {
let tp = list[maxindex]
list[maxindex] = list[index]
list[index] = tp
heapfly(list, length, maxindex)
}
}
let build_heap = function (list:number[], lenght:number){
var lastperent = Math.floor((length-1-1) / 2);
for (var i = lastperent; i >= 0; i--) {
heapfly(list, length, i);
}
}
var list: number[] = [2, 1, 3, 4, 5, 3, 5, 7, 8, 45, 9, 25, 34, 23, 345, 546, 20, 23465, 90, 19];
console.log(list)
var length: number = list.length;
build_heap(list, length)
for (var i = length-1; i >= 0; i--) {
let temp = list[i]
list[i] = list[0]
list[0] = temp
heapfly(list, i, 0)
}
console.log(list)
swap in function
let swap = function (left:number, right:number){
return [right, left]
}
let heapfly = function(list:number[], length:number, index:number){
var leftchild = index*2+1
var rightchild = index*2+2
var maxindex = index
if (leftchild < length && list[leftchild] >list[maxindex]) {
[leftchild, maxindex] = swap(leftchild, maxindex)
}
if (rightchild < length && list[rightchild]>list[maxindex]) {
[rightchild, maxindex] = swap(rightchild, maxindex)
}
if (maxindex != index) {
[list[maxindex], list[index]] = swap(list[maxindex], list[index])
heapfly(list, length, maxindex)
}
}
let build_heap = function (list:number[], lenght:number){
var lastperent = Math.floor((length-1-1) / 2);
for (var i = lastperent; i >= 0; i--) {
heapfly(list, length, i);
}
}
var list: number[] = [2, 1, 3, 4, 5, 3, 5, 7, 8, 45, 9, 25, 34, 23, 345, 546, 20, 23465, 90, 19];
console.log(list)
var length: number = list.length;
build_heap(list, length)
for (var i = length-1; i >= 0; i--) {
[list[i], list[0]]= swap(list[i], list[0])
heapfly(list, i, 0)
}
console.log(list)
[
2, 1, 3, 4, 5,
3, 5, 7, 8, 45,
9, 25, 34, 23, 345,
546, 20, 23465, 90, 19
]
[
1, 2, 3, 3, 4,
5, 5, 7, 8, 9,
19, 20, 23, 25, 34,
45, 90, 345, 546, 23465
]
7. Shell Sort
7.1. Algorithm
A[a] for a -> 0, 1, 2....l-1
for G[g] for g -> 0, 1, ...m
for j -> 0, 1, 2...m-1:
d = G[j]
for i -> d, 2d, 3d
value <- A[i]
index <- i
while(A[index-d] > value && index > 0)
A[index] = A[index-d]
index -= d
A[index] <- value
7.2. Python
def shellsort(list1, N):
G = [7, 5, 3, 1]
for d in G:
i = d
while i < N:
value = list1[i]
index = i
while index > 0 and list1[index-d] > value:
list1[index] = list1[index-d]
index -= d
i += d
list1[index] = value
list1 = [2, 1, 3, 4, 5, 3, 5, 7, 8, 45, 9, 25, 34, 23, 345, 546, 20, 23465, 90, 19, 900]
langdu = len(list1)
shellsort(list1, langdu)
print(list1)
[1, 2, 3, 3, 4, 5, 5, 7, 8, 9, 19, 20, 23, 25, 34, 45, 90, 345, 546, 900, 23465]
7.3. Java
class ShellSorting
{
public static void main(String[] args)
{
int a [] = {2, 1, 3, 4, 5, 3, 6, 7, 8, 4, 9, 45, 9,34, 23,345, 546,20, 23465, 90, 19};
int langdu = a.length;
shellsort(a, langdu);
for (int i = 0; i < langdu; i++) {
System.out.printf("%d ", a[i]);
}
}
private static void shellsort(int []A, int N){
int Grap [] = {7, 5, 3, 1};
for (int i = 0; i < Grap.length; i++) {
int d = Grap[i];
for (int j = d; j < N; j+=d) {
int value = A[j];
int index = j;
while(index > 0 && A[index-d] > value){
A[index] = A[index-d];
index -= d;
}
A[index] = value;
}
}
}
}
1 2 3 3 4 4 5 6 7 8 9 9 19 20 23 34 45 90 345 546 23465
7.4. C/C++
int main(int argc, char *argv[])
{
int A[] = {2, 1, 3, 4, 5, 3, 6, 7, 8, 4, 9, 45, 9,34, 23,345, 546,20, 23465, 90, 19, 23, 45,78};
int langdu = sizeof(A)/sizeof(int);
shellsort(A, langdu);
for (int i = 0; i < langdu; ++i) {
printf("%d ",A[i] );
}
return 0;
}
void shellsort(int A[], int langdu){
int grap[] ={7, 5, 3, 1};
int N = sizeof(grap) / sizeof(int);
for (int j = 0; j < N; ++j) {
int d = grap[j];
for (int i = d; i < langdu; i=i+d) {
int value = A[i];
int index = i;
while (index > 0 && A[index-d] > value) {
A[index] = A[index-d];
index -= d;
}
A[index] = value;
}
}
return;
}
1 2 3 3 4 4 5 6 7 8 9 9 19 20 23 23 34 45 45 78 90 345 546 23465
8. Redix
8.1. Description
N numbers are waiting to be sorted, each number has maxmum d digit, and each digit is from 0 to k
8.2. Algorithmu
Least significant digital OR Most significant digital LSD: from right to left, only sort all numbers according to the last digit(better with conut sort) and then move to left on the second digit, do it again Time complexity $\Theta (d(n+k))$
9. Bucket Sort
9.1. Algorithm
all data are uniformly distributed in a range spilt the range into n equal-sized intervals independently chosen data and put them into corresponding interval sort each interval(better with insert sort) output by list in order of all buckets
10. Count Sort
10.1. Algorithm
A[n] for n from 1 to N will be sorted using additional array C[k] where k from min(A) to max(A) output B[n] for n from 1 to N
for i from 1 to n: C[i] <- 0 for n from 1 to N: C[A[n]]++ for i from 2 to n: C[i] = C[i]+C[i-1] for n from N to 1: B[C[A[n]]] = A[n], C[A[n]]--
10.2. Python
A = [1,4,2,5,3,6,2,5,3,6,3,4,7,8,4] print(A) lengthA = len(A) minA = min(A) maxA = max(A) lengthC = maxA-minA+1 C = [0]*lengthC for n in range(lengthA): C[A[n]-1] = C[A[n]-1]+1 print(C) for i in range(1, lengthC,1): C[i] = C[i]+C[i-1] print(C) B = [0]*lengthA for n in range(lengthA-1,-1,-1): B[C[A[n]-1]-1] = A[n] C[A[n]-1] = C[A[n]-1]-1 print(B)
[1, 4, 2, 5, 3, 6, 2, 5, 3, 6, 3, 4, 7, 8, 4] [1, 2, 3, 3, 2, 2, 1, 1] [1, 3, 6, 9, 11, 13, 14, 15] [1, 2, 2, 3, 3, 3, 4, 4, 4, 5, 5, 6, 6, 7, 8]
11. Dichotomy
11.1. C/C++
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int dichotomy(int **p, int *start, int *end, int x){
if (*p == NULL) {
printf(" This array is empty !\n");
return -1;
}
if (x < *start || x > *end) {
printf("this element is not in the array\n");
return -1;
}
if (x == *start || x == *end) {
return x;
}
int len = 0;
for (int *temp = *p; *temp != *end; temp++) {
len++;
}
int mid = *(*p+len/2);
if (mid == *start || x == *end) {
return -1;
}
if (mid >= x) {
return dichotomy(p, start, &mid, x);
}else {
int * newp = *p+len/2;
return dichotomy(&newp, &mid, end, x);
}
}
int main(int argc, char *argv[])
{
int array[] = {1,3,7,12,45,78,234,678,5678};
int x = 690;
int *p = array;
int *start = array;
int *end1 = &array[8];
int *end = (int *)(&array+1);
int a = dichotomy(&p, start, (end-1), x);
if (a == x) {
printf("the element is found !\n");
}else {
printf("the element is not found !\n");
}
return 0;
}
Using (int *)(&list+1)-1 to find the last elemenet of list[]
#include <stdio.h>
int isinarray(int **p, int *start, int *end, int x){
if (*p == NULL) {
return 0;
}
if (x < *start || x > *end) {
return 0;
}
if (x == *start || x == *end) {
return 1;
}
int i = 0;
for (int *temp = *p; *temp != *end; temp++) {
i++;
}
if (i == 1 && (x != *start || x != *end)) {
return 0;
}
int medium = *(*p+i/2);
if (medium >= x) {
return isinarray(p, start, &medium, x);
}else {
int *m = *p+i/2;
return isinarray(&m, &medium, end , x);
}
}
int main(int argc, char *argv[])
{
int list [] = {1,3,6,9,12,34,56,78,90,123,456,789};
int *p = list;
int x = 39;
if (isinarray(&p, list, (int *)(&list+1)-1, x)) {
printf("IN");
}else {
printf("NOT IN");
}
return 0;
}
NOT IN
12. Stupidmax
#include <stdio.h>
#include <math.h>
#define N 5
int Mdiff(int a[N][N]){
int myglobaldiff = 0;
int mylocaldiff = 0;
int mylocaldiff_tmp = 0;
int diff = 0;
for (int x = 0; x < N; x++) {
for (int i = 0; i < N; ++i) {
mylocaldiff_tmp = a[x][i]-a[x][i];
for (int y = 0; y < N; y++) {
diff = fabs(a[x][i] - a[x][y+i]);
if (y+i < N && diff > mylocaldiff_tmp){
mylocaldiff_tmp = diff;
}
}
if (mylocaldiff_tmp > mylocaldiff){
mylocaldiff = mylocaldiff_tmp;
}
}
if (mylocaldiff > myglobaldiff){
myglobaldiff = mylocaldiff;
}
}
return myglobaldiff;
}
int main(int argc, char *argv[])
{
int a [5][5] = {
{
1,2,3,4,52220
},
{
3,4,62,56,2
},
{
3,4,62,56,82
},
{
10,20,62,56,2220,
},
{
3,4,62,56,29
}
};
int tmpmax = Mdiff(a);
printf("%d", tmpmax);
return 0;
}
13. HoffmannCode
13.1. C/C++
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef struct {
int data;
int parent, lboy, rboy;
}HTNode, *HoffmanTree;
typedef char ** HoffmanCode;
void Select(HoffmanTree HT, int *s1, int *s2, int end){
int min1, min2;
int i = 1;
while (HT[i].parent != 0 && i <= end) {
i++;
}
min1 = HT[i].data;
*s1 = i;
i++;
while (HT[i].parent != 0 && i <= end) {
i++;
}
if (HT[i].data <= min1) {
min2 = min1;
*s2 = *s1;
min1 = HT[i].data;
*s1 = i;
}else {
min2 = HT[i].data;
*s2 = i;
}
for (int j = i+1; j <= end; j++) {
if (HT[j].parent != 0) {
continue;
}
if (HT[j].data <= min1) {
min2 = min1;
*s2 = *s1;
min1 = HT[j].data;
*s1 = j;
}else {
min1 = HT[j].data;
*s2 = j;
}
}
}
void CreateHoffman(HoffmanTree *HT, int *list, int length){
if (length <= 1) {
return;
}
int m = 2*length-1;
*HT = (HoffmanTree)malloc(sizeof(HTNode) * m);
int i;
for (i = 1; i <= length; i++) {
(*HT+i)->data = *(list+i-1);
(*HT+i)->parent = 0;
(*HT+i)->lboy = 0;
(*HT+i)->rboy = 0;
}
for (i = length+1; i <= m; i++) {
(*HT+i)->data = 0;
(*HT+i)->parent = 0;
(*HT+i)->lboy = 0;
(*HT+i)->rboy = 0;
}
for (i = length+1; i <=m; i++) {
int s1, s2;
Select(*HT, &s1, &s2, i-1);
(*HT)[s1].parent = (*HT)[s2].parent = i;
(*HT)[i].lboy = s1;
(*HT)[i].rboy = s2;
(*HT)[i].data = (*HT)[s1].data + (*HT)[s2].data;
}
}
void CreateHoffmanCode(HoffmanCode *hcode, HoffmanTree HT, int length){
*hcode = (HoffmanCode)malloc(sizeof(char * ) * length+1);
char *cd = (char *)malloc(sizeof(char) * length);
cd[length-1] = '\n';
for (int i = 1; i <= length; i++) {
int start = length -1;
int c = i;
int j = HT[c].parent;
while (j != 0) {
if (HT[j].lboy == c) {
cd[--start] = '1';
}
else {
cd[--start] = '0';
}
c = j;
j = HT[j].parent;
}
(*hcode)[i] = (char *)malloc(sizeof(char )*length-start);
strcpy((*hcode)[i], &cd[start]);
}
free(cd);
}
void showHoffmanCode(HoffmanCode hcode, int *list, int length){
printf("Here we go\n");
for (int i = 1; i <= length; i++) {
printf("%d : is %s\n",list[i-1], hcode[i]);
}
}
int main(int argc, char *argv[])
{
HoffmanTree htree;
HoffmanCode hcode;
int list[] = {1,18,2,56,3,4, 44,5,7,34,78,90,234,789};
int length = sizeof(list)/sizeof(int);
CreateHoffman(&htree, list, length);
CreateHoffmanCode(&hcode, htree, length);
showHoffmanCode(hcode, list, length);
return 0;
}
Here we go 1 : is 0000001 18 : is 00001 2 : is 000001 56 : is 0001 3 : is 0000000001 4 : is 000000001 44 : is 00000001 5 : is 0000000000001 7 : is 000000000001 34 : is 00000000001 78 : is 001 90 : is 01 234 : is 0 789 : is 0000000000000
14. JosephusRing
14.1. C/C++
#include <stdio.h>
#include <stdlib.h>
typedef struct node{
int number;
struct node * next;
}person;
person * initLink(int n){
person * head=(person*)malloc(sizeof(person));
head->number=1;
head->next=NULL;
person * cyclic=head;
for (int i=2; i<=n; i++) {
person * body=(person*)malloc(sizeof(person));
body->number=i;
body->next=NULL;
cyclic->next=body;
cyclic=cyclic->next;
}
cyclic->next=head;//首尾相连
return head;
}
void findAndKillK(person * head,int k,int m){
person * tail=head;
//找到链表第一个结点的上一个结点,为删除操作做准备
while (tail->next!=head) {
tail=tail->next;
}
person * p=head;
//找到编号为k的人
while (p->number!=k) {
tail=p;
p=p->next;
}
//从编号为k的人开始,只有符合p->next==p时,说明链表中除了p结点,所有编号都出列了,
while (p->next!=p) {
//找到从p报数1开始,报m的人,并且还要知道数m-1de人的位置tail,方便做删除操作。
for (int i=1; i<m; i++) {
tail=p;
p=p->next;
}
tail->next=p->next;//从链表上将p结点摘下来
printf("出列人的编号为:%d\n",p->number);
free(p);
p=tail->next;//继续使用p指针指向出列编号的下一个编号,游戏继续
}
printf("出列人的编号为:%d\n",p->number);
free(p);
}
int main() {
printf("输入圆桌上的人数n:");
/* int n; */
/* scanf("%d",&n); */
person * head=initLink(n);
printf("从第k人开始报数(k>1且k<%d):",n);
/* int k; */
/* scanf("%d",&k); */
printf("数到m的人出列:");
/* int m; */
/* scanf("%d",&m); */
findAndKillK(head, k, m);
return 0;
}
输入圆桌上的人数n:从第k人开始报数(k>1且k<20):数到m的人出列:出列人的编号为:5 出列人的编号为:10 出列人的编号为:15 出列人的编号为:20 出列人的编号为:6 出列人的编号为:12 出列人的编号为:18 出列人的编号为:4 出列人的编号为:13 出列人的编号为:1 出列人的编号为:9 出列人的编号为:19 出列人的编号为:11 出列人的编号为:3 出列人的编号为:17 出列人的编号为:16 出列人的编号为:2 出列人的编号为:8 出列人的编号为:14 出列人的编号为:7
15. KMPmachting
15.1. C/C++
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
void genertarray(char pattern[], int prefix[], int n){
prefix[0] = 0;
int len = 0;
int i =1;
while (i < n) {
if (pattern[i] == pattern[len]) {
len++;
prefix[i] = len;
i++;
}else {
if (len > 0) {
len = prefix[len-1]; //go the preious len, and matching again
}else {
prefix[i] = len; // in case len <= 0, bzw, the first and second is not matching
i++;
}
}
}
}
void move_array(int prefix [], int n){
int i;
for ( i = n-1; i > 0; i--) {
prefix[i] = prefix[i-1];
}
prefix[0] = -1;
}
void kmp_search(char text[], char pattern[]){
int k = strlen(pattern);
int* prefix =(int *) (malloc(sizeof(int )* k));
genertarray(pattern, prefix, k);
move_array(prefix, k);
// text index i, max n
// pattern index j, max m
int i = 0; int j = 0;
int n = strlen(text);
int m = strlen(pattern);
while (i < n) {
if (j == m-1 && text[i] == pattern[j]) { // if found
printf("Fonund at %d \n", i-j);
j = prefix[j]; // still go forward
}
if (text[i] == pattern[j]) {
i++;j++;
}else {
j = prefix[j]; //if not matching
if (j == -1) { //if the first is not matching
i++;j++;
}
}
}
}
int main(int argc, char *argv[])
{
char pattern[] = "ABABBBA";
char text[] = "JUHkSABABBBABABA";
kmp_search(text, pattern);
return 0;
}
Fonund at 5
15.2. C/C++
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
//sort only the pure given numbers, and change each time the sort direction
int recSort(int *start, int *end, int reverse){
int count = 0;
if (start == NULL || end == NULL) {
return 0;
}
if (start == end || start +1 == end) {
return 0;
}
int* p;
if (reverse)
p = end -1;
else
p = start+1;
while (p < end && p > start ) {
if (*(p-1) < *p) {
int temp = *(p-1);
*(p-1) = *p;
*p = temp;
count++;
}
if (reverse)
p--;
else
p++;
}
if (reverse)
return count + recSort(start+1, end, 0);
else
return count + recSort(start, end-1, 1);
}
int main(int argc, char *argv[]) {
if (argc < 1) {
recSort(NULL, NULL, 0);
return -2;
}
int* f = malloc(sizeof(int) * (argc-1));
if (f == NULL) {
return -3;
}
for (int i = 1; i < argc; i++) {
f[i-1] =atoi(argv[i]);
}
printf("before the sort \n");
for (int i =1 ; i < argc; i++) {
printf("%d\n",f[i-1]);
}
int i= recSort(f, &f[argc-1] , 0);
printf("alles in allem, %d times change \n",i);
printf("after the sort \n");
for (int i =1 ; i < argc; i++) {
printf("%d\n",f[i-1]);
}
free(f);
return 0;
}
16. Longest Substring Without Repeating Characters
16.1. python
class Solution:
def lengthOfLongestSubstring(self, s):
hashmap = {}
lastindex = 0
maxlen = 0
for i in range(len(s)):
if s[i] in hashmap:
lastindex = max(lastindex, hashmap[s[i]]+1)
maxlen = max(maxlen, i-lastindex+1)
hashmap[s[i]] = i
return maxlen
ss = Solution()
print(ss.lengthOfLongestSubstring("abcabcbb"))
print(ss.lengthOfLongestSubstring("abcdefkj"))
print(ss.lengthOfLongestSubstring("abc"))
print(ss.lengthOfLongestSubstring("pwwkew"))
print(ss.lengthOfLongestSubstring("abb"))
print(ss.lengthOfLongestSubstring("abba"))
3 8 3 3 2 2
17. k-way Merge
17.1. description
L1, L2…Lk are all sorted array with n elements, will be mereged into one sorted array
17.2. Naive merge
merge L1 with L2 get l2 merge l2 with L3 get l3 ... Time Compexity $$\Theta(n \cdot logk)$$
17.3. rund merge
L1 with L2 for l2 L3 with L4 for l4 ... L2 with L4 for l4 ...
17.4. Heap merge
build a heap with k element, which are from each array L, extract Max-Heap, and rebuild the Heap, in removed array L with new (next) element
18. Dynamic program
18.1. Description
变量类型, 坐标, 限标 都可以是一维或者多维 在状态转移函数中自己影响自己
19. Maximum subarray
| A1. | \(O(n^3)\) | Erschöpfende Suche/ Brute-Force-Suche/ Exhaustive Search |
|---|---|---|
| A2. | \(O(n^2)\) | Zwischen Prozessen mehr anwenden |
| A3. | \(O(n \log n)\) | Rekursive |
| A4. | \(O(n)\) | Max Maxsuffix |
19.1. blunt force \(O(n^{3})\)
A[a] for = 0 to n-1
max -> -Infty
for i = 1 to n
for j = i to n
for k = i to j
sum = sum+A[k]
if sum > max:
max = sum
return max
19.2. iterative based \(O(n^{2})\)
A[a] for a = 0 to n-1
max = -Infty
for i = 1 to n:
sum = 0
for j = i to n:
sum = sum + A[j]
if sum > max:
max = sum
return max
19.3. dynamic programmierung \(O(n)\)
A[a] for a = 0 to n-1
max = - Infty
init array S with n elemenets 0
S[0] = A[0]
for i = 1 to n-1:
S[i] = max{S[i-1]+A[i], A[i]}
if S[i] > max:
max = S[i]
return max
19.3.1. Algorithm
A[a] for a = 0 to n-1
max = 0
Stmp = 0
for i = 1 to n-1:
Stmp = max{Stmp+A[i], A[i]}
if Stmp > max:
max = Stmp
return max
19.3.2. C/C++
int main(int argc, char *argv[])
{
int MaxSubArray(int A[], int N){
int i, b = 0, maxsum = 0;
for (i = 0; i < N; ++i) {
if (b > 0) {
b += A[i];
}else{
b = A[i];
}
if (b > maxsum) {
maxsum = b;
}
}
return maxsum;
}
int A[] = {2, 1, 3, 4, 5, 3, 6, 7, 8, 4, 9, 45, 9,34, 23,345, 546,20, 23465, 90, 19, 23, 45,78};
int length = sizeof(A)/sizeof(int);
int max = MaxSubArray(A, length);
printf("%d \n",max);
return 0;
}
24794
20. maximum submatrix
20.1. Brute force solution
list all submatrix,
sum = 0
for xstart -> 0,1...l:
for xstop -> xstart+1, xstart+2...l:
for ystart -> 0, 1, 2....l:
for ystop -> ystart+1, ystart+2...l:
for x -> xstart .... xstop:
for y -> ystart .... ystop:
sumsub += A[x][y]
if sumsub > sum:
sum = sumsub
import random
import numpy
def maxsublist(arr, n):
b = 0
sumlist = 0
for j in range(n):
if b > 0:
b += arr[j]
else:
b = arr[j]
if b > sumlist:
sumlist = b
return sumlist
def maxsubmatrix(A, l):
Acolmun = np.zeros(l)
summaxtrix = 0
for i in range(l):
if summaxtrix > 0:
Acolmun += A[i,:]
sumlist = maxsublist(Acolmun, l)
print(Acolmun)
print("the maximum sublist is: {}".format(sumlist))
print("the maximum submatrix is: {}".format(summaxtrix))
else:
Acolmun = A[i,:]
sumlist = maxsublist(Acolmun, l)
print(Acolmun)
print("the maximum sublist is: {}".format(sumlist))
print("the maximum submatrix is: {}".format(summaxtrix))
if sumlist > summaxtrix:
summaxtrix = sumlist
return summaxtrix
import random
l = 8
a = [[]]*l
gsm = [[]]*l
#initialization a random matrix with shape of 8x8
for i in range(l):
a[i] = [random.randint(-5, 5) for x in range(l)]
print("Original random matrix \n")
a = np.array(a)
print(a)
max = 0
for i in range(1, l):
for xstart in range(i-1, l): # x start of submatrix
for xstop in range(i+xstart, l+1-i+1): # x stop of submatrix
for j in range(1, l):
for ystart in range(j-1, l): # y start of submatrix
for ystop in range(j+ystart, l+1-j+1): # y stop of submatrix
lip = [[] for x in range(l)]
count = 0
for x in range(xstart, xstop):
for y in range(ystart, ystop):
lip[x].append(a[x][y])
count += a[x][y]
# if (xstart ==6 and xstop == 8 and ystart == 6 and ystop == 8): #test small submatrix
# print (count);
if count > max:
lipmax = [[] for x in range(l)]
max = count
lipmax = lip
print("maximux submatrix :\n")
lipmax = np.array(lipmax)
for i in range(len(lipmax)):
print("\n")
for j in lipmax[i]:
print("{:>4d}".format(j), end="")
print("\n")
print("The summary is ", max)
print("with dynamic programmierung is {}".format(maxsubmatrix(a, l)))
Original random matrix [[ 4 2 0 -2 5 -3 2 1] [-5 -2 5 1 4 2 -4 0] [-4 1 3 1 3 0 2 3] [ 4 2 -1 1 2 -3 -5 -1] [-4 -3 -4 2 3 1 -4 -3] [ 2 0 5 -5 -2 5 -5 5] [-3 -5 5 4 3 1 -4 2] [-2 -3 5 2 1 2 -3 -5]] -10 maximux submatrix : 0 -2 5 -3 5 1 4 2 3 1 3 0 -1 1 2 -3 -4 2 3 1 5 -5 -2 5 5 4 3 1 5 2 1 2 The summary is 46 [ 4 2 0 -2 5 -3 2 1] the maximum sublist is: 9 the maximum submatrix is: 0 [-1 0 5 -1 9 -1 -2 1] the maximum sublist is: 13 the maximum submatrix is: 9 [-5 1 8 0 12 -1 0 4] the maximum sublist is: 24 the maximum submatrix is: 13 [-1 3 7 1 14 -4 -5 3] the maximum sublist is: 25 the maximum submatrix is: 24 [-5 0 3 3 17 -3 -9 0] the maximum sublist is: 23 the maximum submatrix is: 25 [ -3 0 8 -2 15 2 -14 5] the maximum sublist is: 23 the maximum submatrix is: 25 [ -6 -5 13 2 18 3 -18 7] the maximum sublist is: 36 the maximum submatrix is: 25 [ -8 -8 18 4 19 5 -21 2] the maximum sublist is: 46 the maximum submatrix is: 36 with dynamic programmierung is 46
20.2. dynamic programmierung
import random
import numpy as np
def maxsublist(arr, n):
b = 0
sumlist = 0
for j in range(n):
if b > 0:
b += arr[j]
else:
b = arr[j]
if b > sumlist:
sumlist = b
return sumlist
def maxsubmatrix(A, l):
Acolmun = np.zeros(l)
summaxtrix = 0
for i in range(l):
if summaxtrix > 0:
Acolmun += A[i,:]
sumlist = maxsublist(Acolmun, l)
else:
Acolmun = A[i,:]
sumlist = maxsublist(Acolmun, l)
if sumlist > summaxtrix:
summaxtrix = sumlist
return summaxtrix
l = 8
A = [[]]*l
for i in range(l):
A[i] = [random.randint(-5, 5) for x in range(l)]
A = np.array(A)
print(A)
print(maxsubmatrix(A, l))
[[ 5 -2 3 4 -1 4 -3 4] [ 2 -1 1 -2 -1 2 -4 -5] [ 2 -4 0 5 -4 5 3 4] [ 3 -5 -2 -2 1 -4 4 -3] [ 5 -2 5 4 -2 4 -3 0] [ 5 -2 0 4 -4 -1 3 4] [-3 -4 -3 1 1 -3 -5 4] [ 4 3 5 -5 0 -3 -2 0]] 29
21. Find the sum of a specific value in a list
在一个列表中找到一个特定数值的和
21.1. Python
21.1.1. with recursive
arr = [3, 34, 4, 12, 5, 2]
def res_subset(arr, i, s):
if s == 0:
return True
elif i == 0:
return arr[0] == s
elif arr[i] > s:
return res_subset(arr, i-1, s)
else:
A = res_subset(arr, i-1, s-arr[i])
B = res_subset(arr, i-1, s)
return A or B
print(res_subset(arr, len(arr)-1, 9))
print(res_subset(arr, len(arr)-1, 10))
print(res_subset(arr, len(arr)-1, 11))
print(res_subset(arr, len(arr)-1, 12))
print(res_subset(arr, len(arr)-1, 13))
True True True True False
21.1.2. without rekursive
import numpy as np
arr = [3, 34, 4, 12, 5, 2]
target = 13
result = np.zeros((len(arr), target+1), dtype = bool)
result[: , 0] = True
result[0 , :] = False
result[0 , arr[0]] = True
for i in range(1, len(arr)):
for j in range(1, target+1):
if arr[i] > j:
result[i, j] = result[i-1, j]
else:
A = result[i-1, j-arr[i]]
B = result[i-1, j]
result[i, j] = A or B
print(result[-1][-1])
False
22. Langest increasing subsequence (LIS)
22.1. Python
list1 = [2, 1, 3, 45, 76, 89, 457, 54, 4, 5, 3, 6, 7, 8, 4, 9]
l = len(list1)
a = [1]*l
b = [[] for x in range(l)]
for i in range(l):
for j in range(i):
if (list1[i] > list1[j]) and (a[i] < (a[j] + 1)):
a[i] = a[j]+1
b[i].append(list1[j])
b[i].append(list1[i])
print(a)
maxa = a.index(max(a))
print("the maximun length of LIS of list1 is {}".format(max(a)))
print("the LIS is {}".format(b[maxa]))
[1, 1, 2, 3, 4, 5, 6, 4, 3, 4, 2, 5, 6, 7, 3, 8] the maximun length of LIS of list1 is 8 the LIS is [2, 3, 4, 5, 6, 7, 8, 9]
list1 = [2, 1, 3, 45, 76, 89, 457, 54, 4, 5, 3, 6, 7, 8, 4, 9]
l = len(list1)
a = [1]*l
for i in range(l):
for j in range(i):
if (list1[i] > list1[j]):
a[i] = max(a[i], a[j]+1)
print(a)
print("the maximun length of LIS of list1 is {}".format(max(a)))
[1, 1, 2, 3, 4, 5, 6, 4, 3, 4, 2, 5, 6, 7, 3, 8] the maximun length of LIS of list1 is 8
23. packsack
23.1. 0-1 sack
\(dp[i][j] = max(dp[i-1][j], dp[i-1][j-A[i]] + V[i])\)
23.2. complete sack
k is the total number, if 背包全放每一种时的最大份数 \(dp[i][j] = max(dp[i-1][j], dp[i-1][j-k*A[i]] + k*V[i])\)
23.3. bund sack
n is the bunded number for each variante \(dp[i][j] = max(dp[i-1][j], dp[i-1][j-n*A[i]] + n*V[i])\)
24. Order Statistics
24.1. description
For Array a[i], i from 0 to n-1 we want to find the the k-th biggest element in linear time 1-th biggest is the minimun n-1-th biggest is the maximum
24.2. for minimun and maximum
normal iterative: need 2n-2, each n-1 2 terms iterative:
(min_1, max_1) <- (a[0],a[1])
(min_2, max_2) <- (a[2],a[3])
(min_3, max_3) <- (a[4],a[5])
...
(min_n/2, max_n/2) <- (a[n-2],a[n-1])
min = min_1, max = max_1
for i from 2 to n/2:
if min_i < min:
min = min_i
if max_i > max:
max = max_i
return min, max
24.3. linear approach
index: i
| 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 |
array a[]:
| 2 | 14 | 6 | 27 | 4 | 67 | 24 | 9 | 16 | 45 | 26 | 17 | 20 | 8 | 41 | 23 | 34 | 5 | 36 | 77 | 44 | 3 | 25 | 22 |
looking for the k-th biggest elemenet
divide array a[] into length/5 groups, each group has 5 elemenets, and the last is not required to be 5
--- --- --- --- ---
| 2 | 67 | 26 | 23 | 44 |
--- --- --- --- ---
| 14 | 24 | 17 | 34 | 3 |
--- --- --- --- ---
| 6 | 9 | 20 | 5 | 25 |
--- --- --- --- ---
| 27 | 16 | 8 | 36 | 22 |
--- --- --- --- ---
| 4 | 45 | 41 | 77 |
--- --- --- --- ---
sort all group with insert sorting
--- --- --- --- ---
| 2 | 9 | 8 | 5 | 3 |
--- --- --- --- ---
| 4 | 16 | 17 | 23 | 22 |
--- --- --- --- ---
| 6 | 24 | 20 | 34 | 25 |
--- --- --- --- ---
| 14 | 45 | 26 | 36 | 44 |
--- --- --- --- ---
| 27 | 67 | 41 | 77 |
--- --- --- --- ---
get the mediums of each group
| 6 | 24 | 20 | 34 | 25 |
if at this step, the number of elemenets are more than 5, recursive spilt again
sort group
| 6 | 20 | 24 | 25 | 34 |
get the medium 24. at spilt the array a[] with this element a[7]=24.
if k==7 return 24
if k< 7 looking for k-th biggest elemenet in
| 2 | 14 | 6 | 27 | 4 | 67 |
if k> 7 looking for the (k-16)-th biggest elemenet in
| 9 | 16 | 45 | 26 | 17 | 20 | 8 | 41 | 23 | 34 | 5 | 36 | 77 | 44 | 3 | 25 | 22 |
24.4. complexity
no matter for k > i (i = 7, a[7]=24), we can exculsive the black position
--- --- --- --- ---
| 2 | 8 | 9 | 3 | 5 |
--- --- --- --- ---
| 4 | 17 | 16 | 22 | 23 |
--- --- --- --- ---
| 6 | 20 | 24 | 25 | 34 |
--- --- --- --- ---
| 14 | 26 | 45 | 44 | 36 |
--- --- --- --- ---
| 27 | 41 | 67 | 77 |
--- --- --- --- ---
--- --- --- --- ---
| 3 | 5 |
--- --- --- --- ---
| 22 | 23 |
--- --- --- --- ---
| 25 | 34 |
--- --- --- --- ---
| 14 | 26 | 45 | 44 | 36 |
--- --- --- --- ---
| 27 | 41 | 67 | 77 |
--- --- --- --- ---
\[ \frac{3}{5} \cdot \frac{n}{2} + O(1) = \frac{3n}{10} + O(1)\] elements are definitely excluded
The recursive format is \[ T(n) = T(\frac{n}{5}) + T(\frac{7n}{10}+6) + O(n)\] \[T(n) = O(n)\]
25. Range Minimun Query
25.1. description
array A[i] for i from 0 to n-1 given two number j, k, so 0 < i< j<n-1 return the minimun elements of range A[j]...A[k]
25.2. naiv approach
min = A[0]
for n from 0 to n-2:
for m from 1 to n-1:
for o from n to m:
if A[o] < min:
min = A[o]
obviously the time compexity is \(O(n^{3})\)
25.3. DP naiv approach
with Dynamic Program to iterative scan.
set M[n][n] as empty matrix to save RMQ of array A[n].
M[i][i] = A[i]
for i from 0 to n-2:
M[i][j] = A[i] if A[i] < M[i-1][j]
= M[i-1][j] otherwise
for j from 1 to n-1:
M[i][j] = A[j] if A[j] < M[i][j-1]
= M[i][j-1] otherwise
obviously the time compexity is \(O(n^{2})\)
25.4. addation M approach
set K=ceiling (\(log_2^n\))
set M´[i][k] = RMQ(i, i+2k-1)
—o--------------–—oo-------------------–—o-–—
—+i
------------------–—+\(i+2^{k-1}-1\)
-------------------–—+\(i+2^{k-1}\)
---------------------------------------------–—+\(i+2^k-1\)
M´[*][1] = RMQ(i, i+1)
for i from 0 to n-1:
for k from 2 to K:
M´[i][k] = M´[i][k-1] if A[M´[i][k-1]] < A[M´[i+2^{k-1}][k-1]]
= M´[i+2^{k-1}][k-1] otherwise
get RMQ(i,j)
s = floor(logj-i)
—o-------–—0--–—o-------------------–—o-–—
—i
-----------–—j-2s+1
-------------------–—i+2s-1
--------------------------------------------–—j
for i to i+2^s-1: M´[i][s]
for j-2^s-1 to j: M´[j-2^s-1][s]
RMQ(i,j)= A[M´[i][s]] if A[M´[i][s]] < A[M´[j-2^s-1][s]]
= M´[j-2^s-1][s] otherwise
the time compexity is \(O(n \cdot log^{n})\)
25.5. partional approach
Array A[n]
spilt Array A into block size of \(s = floor(\frac{log^n}{2})\)
we have n/s blocks
------–+ ------–+ ------–+ ------–+ ------–+
------–+ ------–+ ------–+ ------–+ ------–+
we build 2 array h[n/s] and pos[n/s] h[n/s]: contains the minimum element of each block
pos[n/s]: contains the position of the corresponding elements in h when it is still in A.
For RMQ(i, j) i´ = i/s+1 j´ = j/s l = RMQ_h(i´, j´) pos[l] = RMQ(i´s, j´s-1) but the RMQ can still be in [i...i´s] or [j´s...j] so l´ = RMQ[i, i´s] and l´´ = RMQ[j´s, j] return min(l, l´, l´´)
Now comes the question, how to get l´ and l´´ in constant time (in a block)? this can only be solved in special situation
25.6. (\(\pm 1\))RMQ
it called Normalisation.
normalise all block (x,[….]) to (0,x) where \(x \in (-1, +1)^{s}\)
for one block, there are \(2^{s}\) permutation of -1 and +1,
this have time compexity \(O(2^{s}) = O(\sqrt{n})\)
and we compute all permutation probability into a sxs matrix.
for all RMQ query in this block can be saved in this matrix.
this have time compexity of \(s^{2}\)
all together we habe \(O(2^{s} \cdot s^{2}) = O(n)\)
oooo---–—ooooo---–—ooooo–—ooooo-–—oooooo-–—ooooooo
(0, \(x_1\)) (0,\(x_2\)) (0, \(x_3\)) (0,\(x_{n/s}\)) \(m_x_{1}\) \(m_{x_{2}}\) \(m_{x_{3}}\) \(m_{x_{n/s}}\) \(M_x_{1}\) \(M_{x_{2}}\) \(M_{x_{3}}\) \(M_{x_{n/s}}\)
(0,x) normalisation \(m_x\): performance \(M_x\): sxs matrix for permutation
for query of RMQ in a block, auch as for l´ = RMQ[i, i´s], we find the representation of i, i´s in \(m_x\), we can get the corresponding RMQ
25.7. (\(\pm 1\))RMQ for LCA in rooted tree
for a rooted tree, we want to find the Lowest Common Ancestor. for two node u and v, we want to find the common ancestor of u and v and most far away from its root.
for the rooted tree, we do the preprcess to get the following 3 array E[*] (Euler tour) list all the node in tree with DFS, (2n-1) elements L[*] the level of each element in E, this comply with the $\pm$1 property R[*] each element position when they are first time occur in E R[i]= min(E[j]=i|1<j<2n)
find the u and v in R, in R get the corresponding positions in E, get the range from u position to v position find the min in L with the same range we get in E, and return the position of minimum in L get the LCA in E with the position we get in L
LCA(u, v) -> RMQL(E[R[u]], E[R[v]])
25.8. Cartesian tree
this tree has two property, 1, it's a heap, which mean, the parents are all smaller than their childen 2, we can get the original array with the IN-order scan of the tree
How to build cartesian tree
for inserting a new node, we compare it to the root and the rightest edge,
if it is smaller than the root, trun the all(include the root) to be new node's left child
if it is bigger, go down to the next node, if go to the leaf, add it just as right child
if it is bigger, go down to the next node, if it is smaller than one node,
trun all to be the left child, and new node as right chilc
this can be done in \(O(n)\) time compexity
25.9. LCA and RMQ
\[RMQ_{A}(i, j) = LCA_{T_{A}}(i,j)\] where \(T_{A}\) is the cartesian tree of A the root of subtree, which contains i and j, is the RMQ(i,j)
26. Computional Geometry
26.1. Convex combinations
all points p(x, y) between \(p_{1} (x_{1}, y_{1})\) and \(p_{2}(x_{2}, y_{2})\), x1< x < x2 and y1 < y < y2
26.2. Cross Product
\(p_{1} \times p_{2} = det\) \(\begin{pmatrix} 0 & 1 \\ 1 & 0 \end{pmatrix}\) \(=x_{1}y_{2} - x_{2}y_{1}\) cross Product = (sign) * (Aera of Parallelogram)
sign is +: p1 is clockweise from p2 with respect of their common origin, from p1 to (p2-p1) trun to right sign is -: p1 is connterclockweise from p2 with respect of their common origin, from p1 to (p2-p1) trun to left
26.2.1. Application of intersection
Direction: \(d (p_{i}, p_{j}, p_{k}) = (p_{k}-p_{i}) \times (p_{j}-p_{i})\) On-Segment: if one end-point of one Segment is convex combinations of the other Segment
Algorithm: first check if two segments straddles, \(d1 \cdot d2 < 0\) and \(d3 \cdot d4 < 0\) else if any d = 0, check if On-segment otherwise return No
26.2.2. Application of Polar Angle
\(p_{1} \times p_{2} = det\) \(\begin{pmatrix} 0 & 1 \\ 1 & 0 \end{pmatrix}\) \(=x_{1}y_{2} - x_{2}y_{1} > 0\) the sign is positive, p1 to p2 have right trun,
The Polar Angle is p1 < p2
26.3. Sweeping
Check if any two Segments intersect in a Segments Set
sort endpoints of the segments in S from left to right, breaking ties by putting left endpoints before right endpoints, and then by y -coordinates.
T = ∅;
for each point p in the sorted list of endpoints:
if p is the left endpoint of a segment s
Insert(s, T )
if (Above(s, T ) exists and intersects s) or (Below(s, T ) exists and intersects s)
return TRUE
if p is the right endpoint of a segment s
if both Above(s, T ) and Below(s, T ) exist and Above(s, T ) and Below(s, T ) intersect
return TRUE
Delete(s, T )
return FALSE
26.4. Convex Hull
For a Set of points <p0…pn>, we want to find the small Hull, to cover all points.
26.4.1. Graham's Scan
let p0 is the smallest y value in set, and Sorted all other points counterclockweise with their polar angle: \(O(n logn)\)
let S = empty stack
push (p0, S), Push(p1, S), Push(p2, S)
for i from 3 to n:
while from nextTop(S), Top(S) to pi trun left:
pop (S)
push(pi)
return S
This take \(O(n)\)
26.4.2. Jarvis's march
We roll the Paper until we find the point with smallest polar angle, Build a Sequence H, start with p0 just like in Graham's Scan(with smallest y value in Set
start with p0, find the next vertex p1 with smallest polar angle with respect to p0 start with p1, find the next vertex p2 with smallest polar angle with respect to p1 start with p2, find the next vertex p3 with smallest polar angle with respect to p2 ... when we reach the highest y-value vertex,left chain is finished, start to right chain, But from the negative x-axis, until we come back to p0
This take \(O(nh)\)
27. Master Theorem
In a Recursive process, we can form this, \[ T_n = a \cdot T(\frac{n}{b}) + f(n) \], for \(a \geq 1\), \(b \geq 1\). T 代表递归符号, a: 每次递归后重复的次数, n/b: 递归后每个部分的问题规模, f(n): 递归后将所有部分融合的步骤, 作如 下变换:
\[ n^d = f(n) = O(n^{\log_b^a-\epsilon}) \] \[ n^d = f(n) \ge n^{\log_b^a-\epsilon} \] \[ d \ge \log_b^a - \epsilon \] \[ d \ge \log_b^a \] 如果\(\log_b^a\) 在减去一个存在的 \(\epsilon\) 后仍然大于d, 则 :\(T_n = \Theta (n^{\log_b^a})\). 直接\(\log_b^{a}\)
\[ n^d = f(n) = \Theta (n^{\log_b^a}) \] \[ n^d = f(n) = n^{\log_b^a} \] \[ d = \log_b^a \] 如果\(\log_b^a\) 恒等于 d, 则: \(T_n = \Theta (n^{\log_b^a} \cdot \lg^n)\) 直接$logba$乘以\(log^{n}\),注意: 此处是 \(f(n) = \Theta (n^{\log_b^a} log^{k}_{n})\) 中k=0的特列
\[ n^d = f(n) = \Omega(n^{\log_b^a+\epsilon}) \] \[ n^d = f(n) \le n^{\log_b^a+\epsilon} \] \[ d \le \log_b^a +\epsilon \] \[ d \le \log_b^a \] 如果\(\log_b^b\) 在加上一个存在的 ε 后仍然小于d, 则 :\(T_n = \Theta (f(n))\). 直接f(n) 这种情况要检测正则性: if $ ∃ c < 1$ so that, \(af(n/b) \le cf(n)\). if not, Master Theorem can't be used in this case
27.1. 1 \(T(n) = 3T(n/2) + n^{2}\)
a = 3,
b = 2,
\(log_{b}^{a} = log_2^{3}\)
\(\exists \varepsilon\) so that, \(f(n) = \Omega(n^{log_b^a+\varepsilon})\)
Regularity condition: \(af(n/b) = 3(n/2)^2 = 3n^{2}/4\)
\(\exists c > 1\) , so \(3n^{2}/4 \le c \cdot n^{2}\), for example c = 4/5
so \(T(n) = \Omega(f(n)) = \Omega(n^{2})\)
27.2. 2 \(T(n) = 4T(n/2) + n^{2}\)
a = 4
b = 2
\(n^{\log_{b}^{a}} = n^{2} = \Theta(f(n))\)
\(T(n) = \Theta(f(n)logn) = \Theta(n^{2}\log n)\)
27.3. 3 \(T(n) = T(n/2) + 2^{n}\)
a = 1, b = 2
\(n^{\log_{b}^{a}} = \Omega(f(n)) = \Omega(2^{n})\)
Regularity condition: \(af(n/b) = 2^{n/2}\), \(f(n) = 2^{n}\) \(\exists c < 1\), such \(af(n/b) < cf(n)\)
\(T(n) = \Theta(2^{n})\)
27.4. 4 \(T(n) = 2^{n}T(n/2) + n^{n}\)
\(a = 2^{n}\), b = 2,
\(n^{\log_{b}^{a}} = n^{n} = \Theta(f(n))\)
\(T(n) = \Theta(f(n)logn) = \Theta(n^{n}logn)\)
27.5. 5 \(T(n) = 16T(n/4) + n\)
a = 16, b = 4;
\(n^{\log_{b}^{a}} =n^{2} = O(f(n))\)
\(T(n) = \Theta(n^{2})\)
27.6. 6 \(T(n) = 2T(n/2) + nlogn\)
a = 2, b = 2 \(n^{\log_{b}^{a}} =n\)
\(\nexists \epsilon\) so that, \(n^{\log_{b}^{a}-\varepsilon}\) is polynomial bigger than \(O(f(n))\), or \(n^{\log_{b}^{a}+\varepsilon}\) is polynomial smaller than O(f(n)),
But in the extend of second case: \(n^{\log_{b}^{a}} logn = \Theta(f(n))\) so \(T(n) = \Theta(f(n)log^{2}n) = \Theta(n\log^{2}n)\)
27.7. 7 \(2T(n) = 2T(n/2) + n/logn\)
a = 2, b = 2, \(n^{\log_{b}^{a}} =n\)
\(\nexists \epsilon\) so that, \(n^{\log_{b}^{a}-\varepsilon}\) is polynomial bigger than \(O(f(n))\), or \(n^{\log_{b}^{a}+\varepsilon}\) is polynomial smaller than O(f(n)),
But in the extend of second case for k = -1: \(T(n) = \Theta(f(n)loglog^n) = \Theta(n\log\log n)\)
27.8. 8 \(T(n) = 2T(n/4) + n^{0.51}\)
a = 2, b = 4, \(n^{\log_{b}^{a}} = n^{1/2} = \Omega(n^{0.51})\)
Regularity Condition: \(af(n/b)= 2(n/4)^{0.51}\) \(\exists c < 1\), that a(f(n/b)) < c f(n);
\(T(n) = \Theta(n^{0.51})\)
27.9. 9 \(T(n) = 0.5T(n/2) +1/n\)
a = 1/2, b = 2,
\(n^{\log_{b}^{a}} =n^{-1} = \Theta(f(n))\)
\(T(n) = \Theta(f(n)\log n) = log n/n\)
27.10. 10 \(T(n) = 16T(n/4) + n!\)
a = 16, b = 4, \(n^{\log_{b}^{a}} = n^{2} = \Omega(f(n))\)
Regularity condition: \(af(n/b) = 16n!/24\), \(\exists c < 1\), so that af(n/b) < cf(n).
\(T(n) = \Theta(f(n)) = \Theta(n!)\)
27.11. 11 \(T(n) = \sqrt{2} T(n/2) + logn\)
\(a = \sqrt{2}\), b = 2,
\(n^{\log_{b}^{a}} = n^{1/2}= O(f(n))\)
\(T(n) = \Theta(n^{1/2})\)
27.12. 12 \(T(n) = 3T(n/2) +n\)
a = 3, b = 2 \(n^{\log_{b}^{a}} =n^{\log_{2}^{3}} = O(f(n))\)
\(T(n) = \Theta(n^{\log_{2}^{3}})\)
27.13. 13 \(T(n) = 3T(n/3) +\sqrt{n}\)
a = 3, b = 3
\(n^{\log_{b}^{a}} = n = O(f(n))\)
\(T(n) = \Theta(n)\)
27.14. 14 \(T(n) = 4T(n/2) + cn\)
a = 4, b =2,
\(n^{\log_{b}^{a}} =n^{2} = O(f(n))\)
\(T(n) = \Theta(n^{2})\)
27.15. 15 \(T(n) = 3T(n/4) + nlogn\)
a = 3, b = 4,
\(n^{\log_{b}^{a}} = n^{\log_{3}^{4}} =\Omega(f(n))\)
Regularity condition: \(af(n/b) = 3nlog(n/4)/4\) if ∃ c < 1$, so that,af(n/b) < cf(n)
\(\frac{3}{4}n \log n -\frac{3}{4}n\log 4 < c \cdot n \cdot logn <1\) for \(n -> \infty\), \(\frac{3}{4}-\frac{3}{4} \cdot \frac{log 4}{logn} < c < 1\);
so, \(T(n) = \Theta(n\log n)\)
27.16. 16 \(T(n) = 3T(n/3) + n/2\)
a = 3, b = 3,
\(n^{\log_{b}^{a}} = n = \Theta(f(n))\)
\(T(n) = \Theta(f(n)logn) = \Theta(\frac{n}{2}log n)\)
27.17. 17 \(T(n) = 6T(n/3) +n^{2}logn\)
a = 6, b = 3 \(n^{\log_{b}^{a}} = n^{\log_{3}^{6}} = \Omega(f(n))\)
Regularity condition: \(af(n/b) = \frac{2}{3} n^2 log(n/3) < c \cdot n^2 logn\) \(\exists c\) so that, \(\frac{2}{3} log(1/3) < c < 1\)
\(T(n) = \Theta(f(n)) = \Theta(n^{2} logn)\)
27.18. 18 \(T(n) = 4T(n/2) + n/logn\)
a = 4, b = 2,
\(n^{\log_{b}^{a}} = n^{2} = O(f(n))\)
\(T(n) = \Theta(n^{2})\)
27.19. 19 \(T(n) = 64T(n/8) -n^{2}logn\)
a = 64, b = 8, \(n^{\log_{b}^{a}} = n^{2}\)
for extend second case, \(n^{\log_{b}^{a}} logn = \Theta(f(n))\), for k = 1
so \(T(n) = \Theta(n^{2}log^{2}n)\)
27.20. 20 \(T(n) = 7T(n/3) + n^{2}\)
a = 7, b = 3,
\(n^{\log_{b}^{a}} = n^{\log_{3}^{7}} = \Omega(f(n))\)
Regularity condition: \(af(n/b) = \frac{7}{9}n^2\) \(\exists c < 1\), so that af(n/b) < cf(n), such as c = 8/9;
\(T(n) = \Theta(f(n)) = \Theta(n^2)\)
27.21. 21 \(T(n) = 4T(n/2) + logn\)
a = 4, b = 2,
\(n^{\log_{b}^{a}} = n^2 = O(f(n))\)
\(T(n) = \Theta(n^{2})\)
27.22. 22 \(T(n) = T(n/2) + n(2-cosn)\)
a = 1, b = 2,
\(n^{\log_{b}^{a}} = n^{0} = \Omega(n(2-cosn))\)
Regularity condition: if \(af(n/b) < c f(n)\), for c <1. \(\exists c\) so that \(\frac{1}{2} \frac{\frac{n}{2} (2-cos(n/2))}{2-cosn} < c < 1\).
\(T(n) = \Theta(n(2-cosn))\)
28. Universal Hashing
28.1. Definition
We want to save a dataset A localy into dataset B, with has m slots in B and fast access to search, insert, delete operation,
assiging A has n elements.
In oder to guarantee the elements from A will be randomly distributed in B to avoiding the unnecessary collision, we define our universal Hashing hat following property:
\[Pr[h(x)=h(y)] \le 1/m\]
where x, y belongs to dataset A and \(x \neq y\), x < n, y < n,
m is the bins of mapped Dataset B,
h is the wanted universal hashing function instance, from Uninstall Hashing family H
one example of h can be Carter-Wegman hash function
28.2. Carter-Wegman hash function
Carter-Wegman hash function is :
h(x) = [(ax+b)mod p] mod m
assiging p is the nearest prime number bigger than n,
and 0 < a, b < p,
proof: for \(x \neq y\), (ax+b)-(ay+b) = a(x-y) is not divisible by p ? why?? Is the following a theorem?
Theorem?
Assigning \(b\)( in our case: x-y ) is an arbitrary intergel number, and \(p\) is the a prime number and bigger than \(b\), there is not such \(a\) (in our case is also denote as a ) exist, such than 0 < \(a\) < \(p\), and \(ab\) is divisible by \(p\)
If the upper rule holds, then because (ax+b)-(ay+b) = a(x-y) is not divisible by p,
so (ax+b) mod p \(\neq\) (ay+b) mod p
for arbitrary \(a\) anb \(b\),
(ax+b)mod p and (ay+b) mod can have p possibilities and (p-1) possibilities.
so for arbitrary a and b, there are p(p-1) possibilities to locate in B dataset,
because p(p-1) is much more bigger than m, (normally m < n < p),
So we can guarantee that the distribution of elements in B can be very randomly and average.
28.3. Python example
this example is from zydeon github
from math import ceil, log2
from primesieve import nth_prime
from random import randint
import numpy as np
class UniversalHashing:
""" N = #bins
p = prime number st: p >= N """
def __init__(self, N, p=None):
self.N = N
if p is None:
p = nth_prime(1, 1 << max(32, ceil(log2(N))))
assert p >= N, 'Prime number p should be at least N!'
self.p = p
def draw(self):
a = randint(1, self.p - 1)
b = randint(0, self.p - 1)
return lambda x: ((a * x + b) % self.p) % self.N
if __name__ == '__main__':
N = 50 # bins
n = 100000 # elements
H = UniversalHashing(N)
h = H.draw()
T = [0] * N
for _ in range(n):
x = randint(0, n * 10)
T[h(x)] += 1
for i in range(len(T)):
print(T[i] / n) # This should be approximately equal
0.02026 0.02023 0.02001 0.02017 0.01979 0.01949 0.01999 0.01948 0.01958 0.02085 0.02027 0.02041 0.02056 0.02029 0.01867 0.01959 0.02041 0.02004 0.0198 0.02024 0.01969 0.02046 0.02036 0.01984 0.02044 0.02071 0.02033 0.01995 0.01955 0.02052 0.01984 0.01987 0.01958 0.01908 0.01956 0.01964 0.02007 0.02056 0.01997 0.02011 0.02023 0.02024 0.01996 0.01954 0.01988 0.02003 0.01998 0.02037 0.02009 0.01942
Here we can see all elements are randomly distributed in the mapped dataset,
and in upper code a, b and input dataset, all are randomly generated.
But the question is: this can't be reproduced, which means, if we hash the same input again, we will get totally different hash distribution. In practical applications, we have to remember the return index of hashtable, otherwise we can't find it again in hashtable, even we never know if it still in the table.
28.4. universal hash with reproducible
So we want to overcome this problem with reproducible porperty. We fix the a and b, in our following assumpation we set a = b = p-1 applying the Carter-Wegman hash function for the given input data. if the return index is empty, we use it as our hash value.
if the index has been token, we reduce a and b by one, and apply Carter-Wegman hash function again to find a suitable index in hashtable.
over loop this process until one empty hashtable index is return
Here in our reproducible universal hash, if the half hashtable has been token, we double the size of hashtable, so than the over loop process will not be too long. Because the Carter-Wegman hash function use the hashtable size m, so the after resize the hashtable, all elements will be computed again in new hashtable, this take an enormous effort.
28.4.1. check the input data from 100000 to 100100
from math import ceil, log2
from primesieve import nth_prime
from random import randint
import numpy as np
class UniversalHashing:
""" N = #bins
p = prime number st: p >= N """
def __init__(self, N=200, p=None):
self.N = N
self.T = [0] * self.N
if p is None:
p = nth_prime(1, 1 << max(32, ceil(log2(N))))
assert p >= N, 'Prime number p should be at least N!'
self.p = p
self.a = p - 1
self.b = p - 1
def draw(self):
return lambda x: ((self.a * x + self.b) % self.p) % self.N
def hash(x, H):
H.a = H.p - 1
H.b = H.p - 1
while (H.T[H.draw()(x)] != 0):
H.a -= 1
H.b -= 1
H.T[H.draw()(x)] = x
def check(x, H):
H.a = H.p - 1
H.b = H.p - 1
while(x != H.T[H.draw()(x)] and H.T[H.draw()(x)] != 0):
H.a -= 1
H.b -= 1
if(x == H.T[H.draw()(x)]):
print("x :{} is in hashtable".format(x))
return 1
if H.T[H.draw()(x)] == 0:
print("x :{} is not in hashtable".format(x))
return 0
if __name__ == '__main__':
H = UniversalHashing()
Y = [i for i in range(100000, 100100, 1)]
print(Y)
for x in Y:
hash(x, H)
print(H.T)
check(9000, H)
check(100010, H)
[100000, 100001, 100002, 100003, 100004, 100005, 100006, 100007, 100008, 100009, 100010, 100011, 100012, 100013, 100014, 100015, 100016, 100017, 100018, 100019, 100020, 100021, 100022, 100023, 100024, 100025, 100026, 100027, 100028, 100029, 100030, 100031, 100032, 100033, 100034, 100035, 100036, 100037, 100038, 100039, 100040, 100041, 100042, 100043, 100044, 100045, 100046, 100047, 100048, 100049, 100050, 100051, 100052, 100053, 100054, 100055, 100056, 100057, 100058, 100059, 100060, 100061, 100062, 100063, 100064, 100065, 100066, 100067, 100068, 100069, 100070, 100071, 100072, 100073, 100074, 100075, 100076, 100077, 100078, 100079, 100080, 100081, 100082, 100083, 100084, 100085, 100086, 100087, 100088, 100089, 100090, 100091, 100092, 100093, 100094, 100095, 100096, 100097, 100098, 100099] [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 100099, 100098, 100097, 100096, 100095, 100094, 100093, 100092, 100091, 100090, 100089, 100088, 100087, 100086, 100085, 100084, 100083, 100082, 100081, 100080, 100079, 100078, 100077, 100076, 100075, 100074, 100073, 100072, 100071, 100070, 100069, 100068, 100067, 100066, 100065, 100064, 100063, 100062, 100061, 100060, 100059, 100058, 100057, 100056, 100055, 100054, 100053, 100052, 100051, 100050, 100049, 100048, 100047, 100046, 100045, 100044, 100043, 100042, 100041, 100040, 100039, 100038, 100037, 100036, 100035, 100034, 100033, 100032, 100031, 100030, 100029, 100028, 100027, 100026, 100025, 100024, 100023, 100022, 100021, 100020, 100019, 100018, 100017, 100016, 100015, 100014, 100013, 100012, 100011, 100010, 100009, 100008, 100007, 100006, 100005, 100004, 100003, 100002, 100001, 100000, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0] x :9000 is not in hashtable x :100010 is in hashtable
28.4.2. check randint from 1 to 10000
from math import ceil, log2
from primesieve import nth_prime
from random import randint
import numpy as np
class UniversalHashing:
""" N = #bins
p = prime number st: p >= N """
def __init__(self, N=200, p=None):
self.N = N
self.T = [0] * self.N
if p is None:
p = nth_prime(1, 1 << max(32, ceil(log2(N))))
assert p >= N, 'Prime number p should be at least N!'
self.p = p
self.a = p - 1
self.b = p - 1
def draw(self):
return lambda x: ((self.a * x + self.b) % self.p) % self.N
def hash(x, H):
H.a = H.p - 1
H.b = H.p - 1
while (H.T[H.draw()(x)] != 0):
H.a -= 1
H.b -= 1
H.T[H.draw()(x)] = x
def check(x, H):
H.a = H.p - 1
H.b = H.p - 1
while(x != H.T[H.draw()(x)] and H.T[H.draw()(x)] != 0):
H.a -= 1
H.b -= 1
if(x == H.T[H.draw()(x)]):
print("x :{} is in hashtable".format(x))
return 1
if H.T[H.draw()(x)] == 0:
print("x :{} is not in hashtable".format(x))
return 0
if __name__ == '__main__':
H = UniversalHashing()
Y = [randint(1, 10000) for _ in range(100)]
print(Y)
for x in Y:
hash(x, H)
print(H.T)
check(9000, H)
check(100010, H)
[9499, 7809, 9665, 6560, 686, 9560, 6894, 1930, 972, 2659, 50, 8111, 4054, 1588, 9634, 2645, 1875, 6573, 4764, 1851, 3661, 6733, 86, 787, 1139, 1558, 6823, 3650, 2438, 7334, 9074, 3704, 493, 8574, 4280, 6603, 1136, 870, 7313, 7619, 3580, 9129, 1421, 9342, 3873, 9500, 8961, 1279, 3997, 9743, 2565, 8310, 207, 6131, 604, 1294, 9481, 8943, 5951, 8554, 4773, 198, 8479, 8771, 941, 834, 8605, 9254, 3543, 6344, 428, 9841, 3361, 7714, 9908, 2579, 8696, 202, 3235, 6120, 5263, 3912, 2815, 2625, 190, 8407, 4294, 2638, 9100, 7234, 2782, 7793, 9647, 1053, 651, 1309, 9606, 6526, 5017, 2505] [8310, 9254, 9908, 0, 0, 2505, 3704, 651, 0, 3650, 9500, 9499, 0, 0, 8696, 0, 6894, 493, 0, 0, 0, 0, 0, 8943, 686, 0, 4294, 0, 0, 9481, 4280, 1279, 0, 2638, 0, 1875, 9074, 3873, 0, 0, 870, 834, 0, 0, 0, 9665, 0, 5263, 0, 3661, 86, 2659, 0, 0, 0, 0, 4054, 1053, 0, 1851, 50, 0, 0, 9647, 0, 2645, 7234, 0, 0, 9841, 0, 8407, 2438, 0, 0, 3235, 9634, 0, 0, 3543, 0, 0, 428, 0, 0, 2625, 0, 6823, 0, 1421, 0, 7619, 0, 5017, 0, 2815, 0, 0, 0, 0, 0, 7809, 0, 207, 9606, 8605, 604, 6603, 202, 9100, 0, 0, 198, 3997, 0, 0, 0, 7793, 0, 0, 190, 1294, 1588, 787, 0, 0, 0, 0, 2782, 0, 3580, 2579, 0, 0, 0, 0, 8574, 6573, 972, 8771, 0, 0, 0, 0, 0, 2565, 4764, 0, 0, 8961, 6560, 8479, 1558, 0, 0, 0, 8554, 0, 0, 5951, 0, 1309, 0, 4773, 0, 0, 6344, 9743, 9342, 941, 0, 1139, 0, 0, 1136, 0, 7334, 6733, 0, 6131, 1930, 9129, 0, 0, 6526, 0, 0, 3361, 0, 9560, 6120, 0, 0, 0, 0, 0, 7714, 7313, 3912, 8111] x :9000 is not in hashtable x :100010 is not in hashtable
28.4.3. check 100 special input data
we use
Y = [H.N*randint(1, 100) for _ in range(100)]
to generate 100 collision data, we can see all data collided into the same slot if we just use fixed a, b (seeing upper) without a -= 1 and b -= 1. and with the reduction, all special data are average distributed.
from math import ceil, log2
from primesieve import nth_prime
from random import randint
import numpy as np
class UniversalHashing:
""" N = #bins
p = prime number st: p >= N """
def __init__(self, N, p=None):
self.N = N
if p is None:
p = nth_prime(1, 1 << max(32, ceil(log2(N))))
assert p >= N, 'Prime number p should be at least N!'
self.p = p
def draw(self):
a = self.p - 1
b = self.p - 1
# a = randint(1, self.p - 1)
# b = randint(0, self.p - 1)
return lambda x: ((a * x + b) % self.p) % self.N
if __name__ == '__main__':
N = 50 # bins
n = 100000 # elements
H = UniversalHashing(N)
h = H.draw()
T = [0] * N
# for _ in range(n):
# x = randint(0, n * 10)
# T[h(x)] += 1
Y = [H.N*randint(1, 100) for _ in range(100000)]
for x in Y:
T[h(x)] += 1
for i in range(len(T)):
print(T[i] / n) # This should be approximately equal
0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0
from math import ceil, log2
from primesieve import nth_prime
from random import randint
import numpy as np
class UniversalHashing:
""" N = #bins
p = prime number st: p >= N """
def __init__(self, N=200, p=None):
self.N = N
self.T = [0] * self.N
if p is None:
p = nth_prime(1, 1 << max(32, ceil(log2(N))))
assert p >= N, 'Prime number p should be at least N!'
self.p = p
self.a = p - 1
self.b = p - 1
def draw(self):
return lambda x: ((self.a * x + self.b) % self.p) % self.N
def hash(x, H):
H.a = H.p - 1
H.b = H.p - 1
while (H.T[H.draw()(x)] != 0):
H.a -= 1
H.b -= 1
H.T[H.draw()(x)] = x
def check(x, H):
H.a = H.p - 1
H.b = H.p - 1
while(x != H.T[H.draw()(x)] and H.T[H.draw()(x)] != 0):
H.a -= 1
H.b -= 1
if(x == H.T[H.draw()(x)]):
print("x :{} is in hashtable".format(x))
return 1
if H.T[H.draw()(x)] == 0:
print("x :{} is not in hashtable".format(x))
return 0
if __name__ == '__main__':
H = UniversalHashing()
Y = [H.N*randint(1, 100) for _ in range(100)]
print(Y)
for x in Y:
hash(x, H)
print(H.T)
check(9000, H)
check(100010, H)
[14800, 10600, 1400, 4800, 3400, 17800, 12400, 19800, 10200, 9600, 15800, 5200, 8800, 15200, 18200, 1000, 6200, 6800, 16400, 1800, 8800, 12600, 12600, 9600, 16800, 12800, 14400, 3400, 5800, 11600, 19600, 5600, 5400, 9800, 2000, 7800, 15000, 1800, 18800, 16800, 17600, 9000, 18600, 11800, 19200, 16800, 200, 18800, 19200, 6400, 3000, 12000, 2800, 13600, 13600, 16400, 2000, 16400, 19200, 9200, 6200, 11600, 14800, 18200, 17000, 1200, 17800, 12000, 13200, 17200, 9600, 16200, 8200, 15200, 12000, 8400, 15600, 1800, 4000, 1600, 8200, 16000, 9200, 1400, 14000, 1400, 17000, 3200, 2200, 14800, 14200, 11000, 3600, 14200, 8600, 13000, 7400, 7200, 10600, 17600] [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 17600, 10600, 7200, 7400, 13000, 8600, 14200, 3600, 11000, 14200, 14800, 2200, 3200, 17000, 1400, 14000, 1400, 9200, 16000, 8200, 1600, 4000, 1800, 15600, 8400, 12000, 15200, 8200, 16200, 9600, 17200, 13200, 12000, 17800, 1200, 17000, 18200, 14800, 11600, 6200, 9200, 19200, 16400, 2000, 16400, 13600, 13600, 2800, 12000, 3000, 6400, 19200, 18800, 200, 16800, 19200, 11800, 18600, 9000, 17600, 16800, 18800, 1800, 15000, 7800, 2000, 9800, 5400, 5600, 19600, 11600, 5800, 3400, 14400, 12800, 16800, 9600, 12600, 12600, 8800, 1800, 16400, 6800, 6200, 1000, 18200, 15200, 8800, 5200, 15800, 9600, 10200, 19800, 12400, 17800, 3400, 4800, 1400, 10600, 14800, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0] x :9000 is in hashtable x :100010 is not in hashtable
28.4.4. search key
we also used the check function to check if the data is already in hashtable, the check can be done for with and without collision input data. we use 100, 200, 300,… to 20000 as input, so we can check some of it, such as 5000, 9000 5000, or 9000 is in the hashtable even they collided many times.
from math import ceil, log2
from primesieve import nth_prime
from random import randint
import numpy as np
class UniversalHashing:
""" N = #bins
p = prime number st: p >= N """
def __init__(self, N=200, p=None):
self.N = N
self.T = [0] * self.N
if p is None:
p = nth_prime(1, 1 << max(32, ceil(log2(N))))
assert p >= N, 'Prime number p should be at least N!'
self.p = p
self.a = p - 1
self.b = p - 1
def draw(self):
return lambda x: ((self.a * x + self.b) % self.p) % self.N
def hash(x, H):
H.a = H.p - 1
H.b = H.p - 1
while (H.T[H.draw()(x)] != 0):
H.a -= 1
H.b -= 1
H.T[H.draw()(x)] = x
def check(x, H):
H.a = H.p - 1
H.b = H.p - 1
while(x != H.T[H.draw()(x)] and H.T[H.draw()(x)] != 0):
H.a -= 1
H.b -= 1
if(x == H.T[H.draw()(x)]):
print("x :{} is in hashtable".format(x))
return 1
if H.T[H.draw()(x)] == 0:
print("x :{} is not in hashtable".format(x))
return 0
if __name__ == '__main__':
H = UniversalHashing()
Y = [H.N*i for i in range(100)]
print(Y)
for x in Y:
hash(x, H)
print(H.T)
check(5000, H)
check(9000, H)
check(10300, H)
[0, 200, 400, 600, 800, 1000, 1200, 1400, 1600, 1800, 2000, 2200, 2400, 2600, 2800, 3000, 3200, 3400, 3600, 3800, 4000, 4200, 4400, 4600, 4800, 5000, 5200, 5400, 5600, 5800, 6000, 6200, 6400, 6600, 6800, 7000, 7200, 7400, 7600, 7800, 8000, 8200, 8400, 8600, 8800, 9000, 9200, 9400, 9600, 9800, 10000, 10200, 10400, 10600, 10800, 11000, 11200, 11400, 11600, 11800, 12000, 12200, 12400, 12600, 12800, 13000, 13200, 13400, 13600, 13800, 14000, 14200, 14400, 14600, 14800, 15000, 15200, 15400, 15600, 15800, 16000, 16200, 16400, 16600, 16800, 17000, 17200, 17400, 17600, 17800, 18000, 18200, 18400, 18600, 18800, 19000, 19200, 19400, 19600, 19800] [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 19800, 19600, 19400, 19200, 19000, 18800, 18600, 18400, 18200, 18000, 17800, 17600, 17400, 17200, 17000, 16800, 16600, 16400, 16200, 16000, 15800, 15600, 15400, 15200, 15000, 14800, 14600, 14400, 14200, 14000, 13800, 13600, 13400, 13200, 13000, 12800, 12600, 12400, 12200, 12000, 11800, 11600, 11400, 11200, 11000, 10800, 10600, 10400, 10200, 10000, 9800, 9600, 9400, 9200, 9000, 8800, 8600, 8400, 8200, 8000, 7800, 7600, 7400, 7200, 7000, 6800, 6600, 6400, 6200, 6000, 5800, 5600, 5400, 5200, 5000, 4800, 4600, 4400, 4200, 4000, 3800, 3600, 3400, 3200, 3000, 2800, 2600, 2400, 2200, 2000, 1800, 1600, 1400, 1200, 1000, 800, 600, 400, 200, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0] x :5000 is in hashtable x :9000 is in hashtable x :10300 is not in hashtable
29. From binary Heap to Fibonacci Heap
29.1. Binary Heap
Binary Heap example deviced by heap sort
let swap = function (left:number, right:number){
return [right, left]
}
let heapfly = function(list:number[], length:number, index:number){
var leftchild = index*2+1
var rightchild = index*2+2
var maxindex = index
if (leftchild < length && list[leftchild] >list[maxindex]) {
[leftchild, maxindex] = swap(leftchild, maxindex)
}
if (rightchild < length && list[rightchild]>list[maxindex]) {
[rightchild, maxindex] = swap(rightchild, maxindex)
}
if (maxindex != index) {
[list[maxindex], list[index]] = swap(list[maxindex], list[index])
heapfly(list, length, maxindex)
}
}
let build_heap = function (list:number[], lenght:number){
var lastperent = Math.floor((length-1-1) / 2);
for (var i = lastperent; i >= 0; i--) {
heapfly(list, length, i);
}
}
var list: number[] = [2, 1, 3, 4, 5, 3, 5, 7, 8, 45, 9, 25, 34, 23, 345, 546, 20, 23465, 90, 19];
console.log(list)
var length: number = list.length;
build_heap(list, length)
for (var i = length-1; i >= 0; i--) {
[list[i], list[0]]= swap(list[i], list[0])
heapfly(list, i, 0)
}
console.log(list)
[
2, 1, 3, 4, 5,
3, 5, 7, 8, 45,
9, 25, 34, 23, 345,
546, 20, 23465, 90, 19
]
[
1, 2, 3, 3, 4,
5, 5, 7, 8, 9,
19, 20, 23, 25, 34,
45, 90, 345, 546, 23465
]
29.2. Binomial-tree
Definition: if k > 0, \(B_{k} = {B_{0}, B_{1}, B_{2}....B_{k-1}}\).
digraph diagramm {
A0;
B0 -> B1;
C0 -> C1;
C0 -> C2;
C2 -> C3;
D0 -> D1;
D0 -> D2;
D0 -> D3;
D2 -> D4;
D3->D5;
D3 -> D6;
D6 -> D7;
}
1, 2, 4, 8, 16…., node of each tree in foto
k order of Binomial Tree has \(2^{k}\) nodes
29.3. Binomial Heap
all different order Binomial Tree consist Binomial Heap
digraph diagramm {
A0;
A0 -> B0;
B0 -> B1;
B0 -> C0;
C0 -> C1;
C0 -> C2;
C2 -> C3;
C0 -> D0;
D0 -> D1;
D0 -> D2;
D0 -> D3;
D2 -> D4;
D3->D5;
D3 -> D6;
D6 -> D7;
}
Each order has only one Binomial Tree, conlidataion is required at each min-extract, merge
29.4. lazy Binomial Heap
Min-extra, Merge the conlidataion will not be executed, until it's needed
29.5. Fibonacci Heap
key-decrease is also lazy, just cut it off, and add to rootlist amortised operation reduce Min-extra to \(O(log n)\), With Fibonacci array . For all perents, if one child is loss, will be marked as red, if the second also loss, the perent will be cut off, and add to rootlist. Max-damaged-Fibonacci-Heap has Fibonacci number nodes