手撕代碼合集[短時間更新]

退役過久手生了唉..java


目前指望手撕的名單:
1.各類排序(歸併/快排/堆排/冒泡選擇插入/桶排/基數..)
2.各類數據結構(鏈表/堆/帶旋轉的平衡樹)
3.雜c++

主要是C++實現,有空我會接着改成Java(雖然沒差
實現方法儘可能是人盡皆知的那種
而且實現均會經過OJ測試
算法


1.歸併排序數據結構

void merge(int *arr, int lo, int mid, int hi) {
    int *tmp = (int *)malloc((hi-lo+1)*sizeof(int));
    int i = lo, j = mid+1, k = 0;
    while(i<=mid && j<=hi) {
        if(arr[i] <= arr[j]) tmp[k++] = arr[i++];
        else tmp[k++] = arr[j++];
    }
    while(i <= mid) tmp[k++] = arr[i++];
    while(j <= hi)  tmp[k++] = arr[j++];
    memcpy(arr+lo, tmp, k*sizeof(int));
    free(tmp);
}
void mergeSort(int *arr, int lo, int hi) {
    if(lo == hi) return;
    int mid = lo+hi >> 1;
    mergeSort(arr, lo, mid);
    mergeSort(arr, mid+1, hi);
    merge(arr, lo, mid, hi);
}

Java versiondom

package com.caturra.sorting;

import java.util.*;

/**
 * 歸併排序,我的習慣使用全閉區間,[lo,hi]
 * @author Caturra
 *
 */
public class MergeSort {

    public static void sort(Comparable[] comps,int lo,int hi) {
        if(lo >= hi) return;
        int mid = lo+hi >> 1;
        sort(comps,lo,mid);
        sort(comps,mid+1,hi);
        merge(comps,lo,mid,hi);
    }
    
    private static void merge(Comparable[] comps,int lo,int mid,int hi) {
        Comparable[] temp = new Comparable[hi-lo+1];
        int i = lo, j = mid+1, k = 0;
        while(i <= mid && j <= hi) {
            int cmp = comps[i].compareTo(comps[j]);
            if(cmp < 0) {
                temp[k++] = comps[i++];
            } else {
                temp[k++] = comps[j++];
            }
       }
        while(i <= mid) temp[k++] = comps[i++];
        while(j <= hi)  temp[k++] = comps[j++];
        for(k = lo; k <= hi; k++) comps[k] = temp[k-lo]; 
     }
    
    /**
     * 測試樣例,HDU1425
     * @param args
     */
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        while(sc.hasNext()) {
            int n = sc.nextInt();
            int m = sc.nextInt();
            Integer[] arr = new Integer[n];
            for(int i = 0; i < n; i++) {
                arr[i] = sc.nextInt();
            }
            sort(arr, 0, n-1);
            for(int i = 0; i < n/2; i++) {
                arr[i] ^= arr[n-i-1];
                arr[n-i-1] ^= arr[i];
                arr[i] ^= arr[n-i-1];
            }
            for(int i = 0; i < m-1; i++) System.out.print(arr[i]+" ");
            System.out.println(arr[m-1]);
        }
    }
}

2.快排測試

快排幾乎沒敲過,過去太依賴sort了..
須要注意的點:
1.找軸點時i通過的地方必然保證小於將來的基準點,j同理必然大於將來的基準點,所以交錯時則中止掃描
\(comps[1...i-1] \lt p\) 交錯後\(j=i-1\),存在\(comps[0]>comps[j]\)的可能,所以還須要進一步交換知足軸點的定義
既交錯後\(comps[j] \geq comps[0...j-1]\)是最後一步保證的,\(comps[j] \lt comps[j+1...hi]\)是先前的雙指針交換保證的
2.j>=0是恆成立的,最後可能停留在0
3.有序表現很慘ui

Cpp實現參考自鄧俊輝老師的寫法,至關簡潔this

// trick:找軸點前先rand一下才能保證複雜度 
int partition(int *arr, int lo,int hi) {
    swap(arr[lo], arr[lo+rand()%(hi-lo+1)]);
    int val = arr[lo], pivot = lo;
    for(int i = lo+1; i <= hi; i++) {
        if(arr[i] < val) swap(arr[++pivot], arr[i]);
    }
    swap(arr[lo], arr[pivot]);
    return pivot;
}
void quickSort(int *arr, int lo,int hi) {
    if(lo >= hi) return;
    int pivot = partition(arr, lo, hi);
    quickSort(arr, lo, pivot-1);
    quickSort(arr, pivot+1, hi);
}

Java version編碼

package com.caturra.sorting;

import java.util.Scanner;

public class QuickSort {

    public static void sort(Comparable[] comps,int lo,int hi) { 
        if(lo >= hi) return;
        int j = partition(comps,lo,hi);
        sort(comps,lo,j-1);
        sort(comps,j+1,hi);
    }
    
    private static int partition(Comparable[] comps,int lo,int hi) {
        exch(comps,lo,(int)(lo+Math.random()*(hi-lo))); //一般須要隨機化
        Comparable val = comps[lo];
        int i = lo, j = hi+1;
        while(true) {
            while(i < hi && comps[++i].compareTo(val) < 0);
            while(j > lo && comps[--j].compareTo(val) > 0);
            if(i >= j) break;
            exch(comps,i,j);
        }
        exch(comps,lo,j);
        return j;
    }
    
    private static void exch(Object[] comps,int i,int j) {
        Object t = comps[i];
        comps[i] = comps[j];
        comps[j] = t;
    }
    
    public static void main(String[] args) {
        // 測試同上
    }
}

爲了處理重複數過多帶來的劣化而引入三向切分的方法spa

public static void sort(Comparable[] comps,int lo,int hi) {
        if(lo >= hi) return;
        int lt = lo, gt = hi, i = lo+1;
        Comparable val = comps[lo];
        while(i <= gt) {
            int cmp = comps[i].compareTo(val);
            if(cmp < 0) exch(comps,lt++,i++); //comps[i]過小,放入已經排好序的[0,lo)當中,此時和lt連續接壤
            else if(cmp > 0) exch(comps,i,gt--); //放入大於val的一邊,引入的[gt]接着比較
            else i++;
        }
        sort(comps,lo,lt-1);
        sort(comps,gt+1,hi); //此時[lt,gt]都是重複存在的數
    }

3.\(O(n^2)\)排序俱樂部

// 至關直觀的寫法,有一種高逼格寫法學不來( 
void bubbleSort(int *arr, int lo, int hi) {
    bool isSorted = false;
    while(!isSorted) {
        isSorted = true;
        for(int i = lo; i < hi; i++) {
            if(arr[i] > arr[i+1]) {
                swap(arr[i], arr[i+1]);
                isSorted = false;
            }
        }
    }
}
/***************************************************/
//trick:倒過來交換是不斷挑選最優插入點的過程 
void insertSort(int *arr, int lo, int hi) {
    for(int i = lo+1; i <= hi; i++) {
        int j = i;
        while(j>lo && arr[j]<arr[j-1]) { 
            swap(arr[j], arr[j-1]);
            --j;
        }
    }
}
/***************************************************/
// 毫無實現難度 
void selectSort(int *arr, int lo, int hi) {
    for(int i = lo; i <= hi; i++) {
        int minIdx = i;
        for(int j = i; j <= hi; j++) {
            if(arr[j] < arr[minIdx]) {
                minIdx = j;
            }
        }
        swap(arr[i], arr[minIdx]);
    }
}

4.heap簡略版 / 沒有封裝堆排 / 沒有O(n)構造

struct Heap {
    int heap[MAXN],tot;
    void init(){
        tot=0;
    }
    void insert(int val) {
        heap[++tot]=val;
        int now = tot;
        while(heap[now] < heap[now>>1]) {
            swap(heap[now],heap[now>>1]);
            now >>= 1; 
        }
    }
    int pop() {
        int res = heap[1];
        heap[1] = heap[tot--];
        int now = 1;
        while(now*2 <= tot) {
            int nxt = now<<1;
            if(nxt+1<=tot && heap[nxt+1] < heap[nxt]) nxt++; //  find min
            if(heap[now] < heap[nxt]) return res;
            swap(heap[now], heap[nxt]);
            now = nxt;
        }
        return res;
    }
}h;

5.KMP

char text[MAXN], pattern[MAXN];
int f[MAXN], nxt[MAXN];
void init() {
    int len = strlen(pattern+1);
    int j = 0;
    nxt[1] = 0;
    for(int i = 2; i <= len; i++) {
        while(j>0 && pattern[i]!=pattern[j+1]) j = nxt[j];
        if(pattern[i] == pattern[j+1]) j++;
        nxt[i] = j;
    }
}
int match() {
    int n = strlen(text+1), m = strlen(pattern+1);
    int j = 0, ans = 0;
    for(int i = 1; i <= n; i++) {
        while(j>0 && (j==m || text[i]!=pattern[j+1])) j = nxt[j];
        if(text[i] == pattern[j+1]) j++;
        f[i] = j;
        if(f[i] == m) ans++;
    }
    return ans;
}

6.Huffman編碼(醜

#include<bits/stdc++.h>
using namespace std;
const int MAXN = 1e5+11;

struct Node {
    int lc, rc;
    int weight;
    char val;
    int id;
    Node() {}
    Node(int _id,int _weight,char _val) {
        id = _id, weight = _weight, val = _val,
        lc = rc = 0;
    }
    bool operator < (const Node &rhs) const {
        return weight > rhs.weight;
    }
}huffman[MAXN]; int tot; 
priority_queue<Node> pq;
string ans[128];
string tmpBit;

void dfs(int now) {
    if(huffman[now].val) {
        ans[huffman[now].val] = tmpBit;
    }
    
    tmpBit.push_back('0');
    if(huffman[now].lc) dfs(huffman[now].lc);
    tmpBit.pop_back();
    
    tmpBit.push_back('1');
    if(huffman[now].rc) dfs(huffman[now].rc);
    tmpBit.pop_back();
}

int num[128];
string str;

int main() {
    
    while(cin >> str) {
        
        memset(num,0,sizeof num);
        tot = 0;
        while(!pq.empty()) pq.pop();
        
        int all = 0, allId = 0;
        
        for(int i = 0; i < str.length(); i++) {
            if(num[str[i]] == 0) all++, allId = str[i];
            num[str[i]]++;
        }
        
        if(all == 1) {
            cout << (char)allId <<":: " << 0 << endl;
            cout << "totLength: " << str.length() << endl; 
            cout << "rate: " << str.length() << endl; 
            continue;
        }
        
        for(int i = 1; i < 128; i++) {
            if(!num[i]) continue;
            huffman[++tot] = Node(tot,num[i],i);
            pq.push(huffman[tot]);
        }
        
        while(pq.size() > 1) {
            Node tmp1 = pq.top(); pq.pop();
            Node tmp2 = pq.top(); pq.pop();
            
            huffman[++tot] = Node(tot,tmp1.weight+tmp2.weight,0);
            
            huffman[tot].lc = tmp1.id;
            huffman[tot].rc = tmp2.id;
            
            pq.push(huffman[tot]);
        }
        
        for(int i = 0; i < 128; i++) ans[i].clear();
        tmpBit.clear();
        dfs(tot);
        long long totLen = 0;
        
        vector<char> characters;
        int uniqueLength = 0;
        
        for(int i = 0; i < 128; i++) {
            if(num[i]) {
                cout<<(char)i<<":: "<<ans[i]<<endl;
                characters.push_back(i);
                uniqueLength += ans[i].length(); 
            }
            totLen += num[i] * ans[i].length();
        }
        
        cout << "totLength: " << totLen << endl; 
        cout << "rate: " << 8.0*str.length() / totLen << endl;
        
        int *encoded = (int *) malloc(((uniqueLength+31)/32)*sizeof(int));
        memset(encoded,0,sizeof encoded);
        int nowLength = 0;
        for(int i = 0; i < characters.size(); i++) {
            for(int j = 0; j < ans[characters[i]].size(); j++) {
                int x = nowLength / 32;
                int y = nowLength % 32;
                int z = 0;
                if(ans[characters[i]][j] == '1') {
                    z = 1;
                }
                encoded[x] |= (z<<y);
                nowLength++;
            }
        }
        
        cout<<"ordered table: ";
        for(int i = 0; i < characters.size(); i++) {
            cout<<(char)characters[i]<<" ";
        } 
        cout<<endl;
        nowLength = 0;
        for(int i = 0; i < characters.size(); i++) {
            for(int j = 0; j < ans[characters[i]].size(); j++) {
                int x = nowLength / 32;
                int y = nowLength % 32;
                cout<<(encoded[x]>>y&1);
                nowLength++;
            }
            cout<<"|";
        }
        cout<<endl;
        
    }
    return 0; 
}

堆(new version)
此次的堆實現是按照算法導論的思路寫的

import java.util.Arrays;
import java.util.Scanner;

// 默認大根堆
public class MyHeap {

    public int[] heap;
    public int size;
    public boolean heapStatus;

    public MyHeap(int capacity) {
        heap = new int[capacity];
        size = 0;
    }


    public int down(int size,int idx) {
        int mx = 0;
        int res = heap[idx];
        while(mx != idx) {
            mx = idx;
            int lc = idx << 1;
            int rc = idx << 1 |1;
            if(lc <= size && heap[lc] > heap[idx]) {
                mx = lc;
            }
            if(rc <= size && heap[rc] > heap[mx]) {
                mx = rc;
            }
            if(mx != idx) {
                res = Math.max(res,heap[mx]);
                swap(heap,mx,idx);
                idx = mx; // idx換成了mx 但val仍是原來下沉的那個
                mx = 0;
            }
        }
        return res;
    }

    public void build(int[] arr) {
        for(int i = 1; i <= arr.length; i++) {
            heap[i] = arr[i-1];
        }
        size = arr.length;
        for(int i = size>>1; i >= 1; --i) {
            down(size,i);
        }
        heapStatus = true;
    }

    public void swap(int[] arr,int i,int j) {
        int t = arr[i];
        arr[i] = arr[j];
        arr[j] = t;

    }

    public void heapSort(int[] arr) {
        build(arr);
        for(int i = size; i >= 2; --i) {
            swap(heap,1,i);
            down(i-1,1);
        }
    }

    public void up(int i) {
        while(i > 1 && heap[i] > heap[i>>1]) {
            swap(heap,i,i>>1);
            i >>= 1;
        }
    }

    public void insert(int val) {
        heap[++size] = val;
        up(size);
    }

    public int remove() {
        int res = down(size,1);
        swap(heap,1,size--);
        down(size,1);
        return res;
    }

    public static void main(String[ ] args) {
        MyHeap heap = new MyHeap(222);
        int[] arr = new int[] {0,5,2,67,4,1,6,9,3,2,11,7,0};
        heap.build(arr);
        System.out.println(Arrays.toString(heap.heap));
        System.out.println("built");
        heap.insert(5);
        heap.insert(666);
        heap.insert(-1);
        heap.remove();
        System.out.println("rm:"+heap.remove());
//        System.out.println("rm:"+heap.remove());
//        heap.heapSort(arr);
        System.out.println(Arrays.toString(heap.heap));
    }
}

LCA-RMQ實現

import java.util.HashMap;

class TreeNode {
    int val;
    TreeNode left;
    TreeNode right;
    TreeNode(int x) { val = x; }
}

class Solution {

    public HashMap<TreeNode,Integer> dep = new HashMap<>();
    public HashMap<TreeNode,TreeNode>[] p = new HashMap[20];

    public void dfs(TreeNode rt,TreeNode fa) {
        if(fa == null) {
            dep.put(rt,0);
            p[0].put(rt,rt);
        }
        else {
            dep.put(rt,dep.get(fa)+1);
            p[0].put(rt,fa);
        }
        for(int i = 1; i < 20; i++) {
            p[i].put(rt,p[i-1].get(p[i-1].get(rt)));
        }
        if(rt.left != null) dfs(rt.left,rt);
        if(rt.right != null) dfs(rt.right,rt);
    }

    TreeNode lca(TreeNode u,TreeNode v) {
        if(dep.get(u) < dep.get(v)) {
            TreeNode t = u;
            u = v;
            v = t;
        }
        for(int i = 0; i < 20; i++) {
            if((dep.get(u)-dep.get(v) >>i&1) == 1) {
                u = p[i].get(u);
            }
        }
        if(u == v) return u;
        for(int i = 19; i >= 0; --i) {
            if(p[i].get(u) != p[i].get(v)) {
                u = p[i].get(u);
                v = p[i].get(v);
            }
        }
        return p[0].get(u);
    }

    public TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) {
        if(root == null || p == null || q == null) return null;
        for(int i = 0; i < 20; i++) this.p[i] = new HashMap<>();
        dfs(root,null);
        return lca(p,q);
    }
}
相關文章
相關標籤/搜索