劍指offer算法---Go實現

簡介

最近在準備面試,發現一個不錯的網站推薦給你們。也但願經過Go實現來把裏面 劍指offer算法 的題作一下。
若是以爲幫到了你,但願能爲我點個贊呀。
若是發現代碼有錯,很是但願您可以在留言中指出。
https://github.com/CyC2018/CS...
文章只貼本身寫的代碼,題目的全部內容和解題思路都在上面的網站裏。
一些比較簡單無聊的題,就跳過。。html

未完待續。

歸併排序,快排,堆排序

這一節不出如今劍指offer裏邊,可是常常面試問到。
1.歸併排序ios

package main

import (
    "math/rand"
    "time"
)

// 產生n個隨機數
func CreateList(list []int, n int) []int {
    s1 := rand.NewSource(time.Now().Unix())
    r1 := rand.New(s1)
    for i := 0; i < n; i++ {
        list = append(list, r1.Intn(100))
    }
    return list
}

func Merge(list []int, a, b int) {
    var (
        i, j int
        mid  int
        pos  int
    )

    temp := make([]int, len(list))
    copy(temp, list)
    i = a
    mid = (a + b) / 2
    j = mid + 1
    pos = a
    for i <= mid && j <= b {
        if temp[i] < temp[j] {
            list[pos] = temp[i]
            pos++
            i++
        } else {
            list[pos] = temp[j]
            pos++
            j++
        }
    }
    for i <= mid {
        list[pos] = temp[i]
        pos++
        i++
    }
    for j <= b {
        list[pos] = temp[j]
        pos++
        j++
    }
}

// 左閉右閉[a,b]
func MergeSort(list []int, a, b int) {
    if a+1 >= b {
        if list[a] > list[b] {
            list[a], list[b] = list[b], list[a]
        }
        return
    }
    // 排序包括下標(a+b)/2的值
    MergeSort(list, a, (a+b)/2)

    MergeSort(list, (a+b)/2+1, b)

    Merge(list, a, b)
}

func main() {
    // var inputList = []int{5, 3, 8, 22, 76, 1, 31, 55}
    var inputList = []int{}
    inputList = CreateList(inputList, 10)

    MergeSort(inputList, 0, len(inputList)-1)
    fmt.Println(inputList)
}

2.快排c++

// 左閉右閉[a,b]
func QuickSort(list []int) {
    var (
        midValue   int
        head, tail int
    )
    if len(list) <= 1 {
        return
    }
    head = 1
    midValue = list[0]
    tail = len(list) - 1
    for head < tail {
        for list[head] < midValue {
            head++
            if head >= tail {
                goto END
            }
        }
        for list[tail] > midValue {
            tail--
            if head >= tail {
                goto END
            }
        }
        list[head], list[tail] = list[tail], list[head]
        head++
        tail--
    }
END:
    if list[head] > midValue {
        list[0], list[head-1] = list[head-1], list[0]

        QuickSort(list[0 : head-1])
        QuickSort(list[head:])
    } else {
        list[0], list[head] = list[head], list[0]

        QuickSort(list[0:head])
        QuickSort(list[head+1:])
    }
}

3.堆排序
推薦文章:
https://www.cnblogs.com/cheng...
https://blog.csdn.net/MoreWin...git

// i爲處理節點,其是從孩子節點向下影響堆。
// n爲堆的節點數
// 其存在一個前提假設,就是兩個孩子都已是大頂堆
func MaxHeapFixDown(list []int, i int, n int) {
    var (
        parent int
        kid    int
    )
    parent = i
    // (i+1)*2 和 (i+1)*2 -1 :爲孩子節點
    kid = (i+1)*2 - 1
    for kid < n {
        // 取孩子最大的一個
        if kid+1 < n && list[kid+1] > list[kid] {
            kid++
        }
        // 最大的孩子和父親比較
        if list[parent] < list[kid] {
            // 若是孩子大,則交換
            list[parent], list[kid] = list[kid], list[parent]
            // 父親,孩子換人
            parent = kid
            kid = (parent+1)*2 - 1
            continue
        } else {
            // 若是父親大,則退出,主要是假設在兩個子樹原本都是大頂堆
            return
        }
    }
}

// 大頂堆生成
func CreateMaxHeap(list []int) {
    // 從最小的非葉子節點開始生成。
    // 這樣就會一直處在 兩個孩子都已是大頂堆 的前提
    // n := (len(list) - 1) / 2
    for n := (len(list) - 1) / 2; n >= 0; n-- {
        MaxHeapFixDown(list, n, len(list))
    }
}

// 從小到大排序
func HeapSort(list []int) {

    //1.大頂堆生成
    CreateMaxHeap(list)
    // 根與最後一個交換,此時咱們概念中的堆的大小將減一
    // 也就是少一個節點不在大頂堆的範圍內
    for n := len(list) - 1; n > 0; n-- {
        list[0], list[n] = list[n], list[0]
        // 由於動了根節點,對根節點進行處理
        MaxHeapFixDown(list, 0, n-1)
    }

}
func main() {
    var inputList = []int{5, 3, 8, 22, 76, 1, 31, 55}
    // var inputList = []int{}
    // inputList = CreateList(inputList, 10)

    HeapSort(inputList)
    fmt.Println(inputList)
}

希爾排序

#include <iostream>
using namespace std;

template <class T>
        int getArrayLen(T& array){
            return sizeof(array)/sizeof(array[0]);
        }
int main(){
    int a[6] = {1,4,2,7,3,9};
    int seq;
    int gap,i,j,k;
    int arrayLen;
    arrayLen = getArrayLen(a);
    gap = arrayLen;

    for(gap = gap/2;gap > 0;gap = gap/2){
        for(j = gap;j < arrayLen;j++){

            for(k = j; k-gap >= 0 && a[k] < a[k-gap]; k -= gap){
                int temp = a[k];
                a[k] = a[k-gap];
                a[k-gap] = temp;
            }
        }
    }
    for(i = 0;i < 6;i++){
        cout << a[i] << " " << endl;
    }
}

線段樹

c++版本。。
很好的教程視頻:https://www.bilibili.com/vide...github

#include <iostream>
using namespace std;
#define MAX_SIZE 1000

int CreateTree(int *a,int *tree,int root,int start,int end){
//    cout << "start:" << start << "\t\t" << "end:" << end << endl;
    if(start == end){
//        cout << "tree[rNote] = " << a[start] << endl;
        tree[root] = a[start];
        return tree[root];
    }

    int mid = (start+end)/2;
    int lc,rc;
    int lres,rres;
    lc = root*2+1;
    rc = root*2+2;


    lres = CreateTree(a,tree, lc, start,mid);
    rres = CreateTree(a,tree, rc,mid+1, end);
//    cout << "lres:" << lres << "\t\t" << "rres:" << rres << endl;
    tree[root] = lres +rres;
    return tree[root];
}

void Update(int *a,int *tree,int root,int start,int end,int updateNode,int val){
    if(start == end){
        a[updateNode] = val;
        tree[start] = val;
        return;
    }
    int mid = (start+end)/2;
    int lc,rc;
    lc = root*2 + 1;
    rc = root*2 + 2;

    if(updateNode<=mid){
        Update(a,tree,lc,start,mid,updateNode,val);
    }else{
        Update(a,tree,rc,mid+1,end,updateNode,val);
    }
    tree[root] = tree[lc] + tree[rc];
    return;
}

int query(int *a,int *tree,int root,int start,int end,int left,int right){
    int mid = (start + end)/2;
    int lc,rc;
    int lres,rres;
    lc = root*2 + 1;
    rc = root*2 + 2;

    cout << "start:" << start << "\t\t" << "end:" << end << endl;

    if(right < start || left >end ){
        return 0;
    }else if (start == end){
//        cout << tree[start] << endl;
        return a[start];
    }else if(left<=start && right>=end){
//        cout << tree[start] << endl;
        return tree[root];
    }else{
        lres = query(a,tree,lc,start,mid,left,right);
        rres = query(a,tree,rc,mid+1,end,left,right);
//        cout << tree[start] << endl;
        return  lres +rres;
    }
}

int main(){
    int a[6] = {1,4,2,7,3,9};
    int tree[MAX_SIZE];
    CreateTree(a,tree,0,0,5);

    cout << "done"  <<endl;
    Update(a,tree,0,0,5,5,1);
    cout << "done"  <<endl;
    for(int i=0;i < 6;i++){
        cout << tree[i] << " ";
    }
    cout << "done"  <<endl;
    cout << query(a,tree,0,0,5,2,5);

}

紅黑樹

推薦文章:
https://zhuanlan.zhihu.com/p/...
https://blog.csdn.net/v_JULY_...
性質面試

  1. 每一個結點要麼是紅的要麼是黑的。
  2. 根結點是黑的。
  3. 每一個葉結點(葉結點即指樹尾端NIL指針或NULL結點)都是黑的。
  4. 若是一個結點是紅的,那麼它的兩個兒子都是黑的。
  5. 對於任意結點而言,其到葉結點樹尾端NIL指針的每條路徑都包含相同數目的黑結點。

clipboard.png

題目3-9

3.數組中重複的數字算法

// 數組中重複的數字
func topic3() {
    // 交換函數
    swap := func(list []int, i, j int) {
        list[i], list[j] = list[j], list[i]
    }

    input := []int{2, 3, 1, 0, 2, 5}
    for i := 0; i < len(input); i++ {
        // 將轉換後
        for i != input[i] {

            // i要換到input[i]的位置,可是若是input[i]位置的值(intput[input[i]])等與input[i],說明重複來了
            if input[i] == input[input[i]] {
                fmt.Println(input[i], "重複")
                goto END
            }
            swap(input, i, input[i])
        }
    }
END:
    fmt.Println("done")
}

4.二維數組中的查找數組

// 我本身最初想到的方法
// 時間消費在算等差值d這個數組(這裏懶得寫),以及下面的關於row的循環
func topic4() {
    list := [5][5]int{
        {1, 4, 7, 11, 15},
        {2, 5, 8, 12, 19},
        {3, 6, 9, 16, 22},
        {10, 13, 14, 17, 24},
        {18, 21, 23, 26, 30},
    }
    // 等差值,都爲3只是特殊
    d := [5]int{3, 3, 3, 3, 3}

    // 行列數
    col := 5
    row := 5
    var input int
    fmt.Scanf("%d", &input)

    for i := 0; i < row; i++ {
        if input > list[i][col-1] || input < list[i][0] {
            // 比該行最大還大或者比最小的還小,下一行
            continue
        } else {
            if (input-list[i][0])%d[i] == 0 {
                fmt.Println("true")
                goto DONE
            }
            continue
        }
    }
    fmt.Println("false")
DONE:
    fmt.Println("done")
}

7.重建二叉樹app

type treeNode struct {
    value int
    left  *treeNode
    right *treeNode
}

func CreateTree(preorder, inorder []int) (ptNode *treeNode) {

    var (
        leftChiledSize int
    )

    if len(preorder) != len(inorder) {
        fmt.Println("error")
        // debug
        panic("err1")
    }
    ptNode = &treeNode{
        left:  nil,
        right: nil,
        value: preorder[0],
    }
    // 遞歸退出條件
    if len(preorder) == 1 {
        return ptNode
    }

    leftChiledSize = GetLeftChiledSize(preorder[0], inorder)
    ptNode.left = CreateTree(preorder[1:1+leftChiledSize], inorder[0:leftChiledSize])
    ptNode.right = CreateTree(preorder[1+leftChiledSize:], inorder[leftChiledSize+1:])
    return ptNode
}

//獲取左子樹節點數
func GetLeftChiledSize(root int, inorder []int) int {
    for i := 0; i < len(inorder); i++ {
        if root == inorder[i] {
            return i
        }
    }
    // debug
    panic("err2")
}

// 後續遍歷
func PostOrderTraversal(ptree *treeNode) {
    if ptree.left == nil && ptree.right == nil {
        fmt.Println(ptree.value)
        return
    }

    if ptree.left != nil {
        PostOrderTraversal(ptree.left)
    }
    if ptree.right != nil {
        PostOrderTraversal(ptree.right)
    }
    fmt.Println(ptree.value)
}

func topic7() {
    preorder := []int{3, 9, 20, 15, 7}
    inorder := []int{9, 3, 15, 20, 7}
    treeRoot := CreateTree(preorder, inorder)
    PostOrderTraversal(treeRoot)
}

8.二叉樹的下一個結點ide

type treeNode struct {
    value  int
    parent *treeNode
    left   *treeNode
    right  *treeNode
}

func CreateTree(preorder, inorder []int) (ptNode *treeNode) {

    var (
        leftChiledSize int
    )

    if len(preorder) != len(inorder) {
        fmt.Println("error")
        // debug
        panic("err1")
    }
    ptNode = &treeNode{
        parent: nil,
        left:   nil,
        right:  nil,
        value:  preorder[0],
    }
    // 遞歸退出條件
    if len(preorder) == 1 {
        return ptNode
    }

    leftChiledSize = GetLeftChiledSize(preorder[0], inorder)
    ptNode.left = CreateTree(preorder[1:1+leftChiledSize], inorder[0:leftChiledSize])
    ptNode.left.parent = ptNode
    ptNode.right = CreateTree(preorder[1+leftChiledSize:], inorder[leftChiledSize+1:])
    ptNode.right.parent = ptNode
    return ptNode
}

func GetLeftChiledSize(root int, inorder []int) int {
    for i := 0; i < len(inorder); i++ {
        if root == inorder[i] {
            return i
        }
    }
    // debug
    panic("err2")
}

// 前序遍歷獲取節點
func PreOrderGetNode(ptree *treeNode, target int) (res *treeNode) {
    if ptree.value == target {
        return ptree
    }
    if ptree.left != nil {
        if res = PreOrderGetNode(ptree.left, target); res != nil {
            return res
        }
    }
    if ptree.right != nil {
        if res = PreOrderGetNode(ptree.right, target); res != nil {
            return res
        }
    }

    // debug
    // fmt.Println("can not find")

    return nil
}

//獲取中序遍歷下的下一個節點
func InOrderNext(pt *treeNode) (res *treeNode) {
    // 有右子樹 -> 取右樹最左節點
    if pt.right != nil {
        circle := pt.right
        for circle.left != nil {
            circle = circle.left
        }
        return circle
    }
    // 無右子樹 -> 向上找第一個左連接指向的樹包含該節點的祖先節點。
    circle := pt
    for circle.parent != nil {
        if circle.parent.left == circle {
            return circle.parent
        }
        circle = circle.parent
    }

    // debug
    fmt.Println("cannot find")

    return nil
}

func topic8() {
    preorder := []int{3, 9, 20, 15, 7}
    inorder := []int{9, 3, 15, 20, 7}
    // 生成樹
    rootTree := CreateTree(preorder, inorder)

    // 前序遍歷獲取值爲15的節點
    target := PreOrderGetNode(rootTree, 7)

    res := InOrderNext(target)
    if res == nil {
        fmt.Println("沒有下一個節點")
    } else {
        fmt.Println(res.value)
    }
}

標題文字

相關文章
相關標籤/搜索