Brantou的日常

二三事


  • 首页

  • 归档

  • 分类

  • 标签

  • 关于

  • 搜索

Dot Source Code Blocks in Org Mode

发表于 2018-04-23 | 分类于 org-mode |

1 简介

Dot 是 Graphviz 开源图形可视化软件中的六个布局程序之一,由 AT&T 创建。 Graphviz 布局程序采用简单的文本图形描述并以各种格式制作有用的图表。 Dot 代码块默认调用 dot 布局程序,但可以配置为调用任何其他五个 Graphviz 布局程序。

图形可视化在很多技术领域都有应用,它常常用于探索大型数据集。 Org 模式中的典型用法是将点源代码块链接到另一种语言的源代码块,该代码块负责将数据表转换为其中一种 Graphviz 布局语言的源代码。

2 配置

(org-babel-do-load-languages
 'org-babel-load-languages
 '((dot . t))) ; this line activates dot

3 使用示例

a Hello
b World
(mapcar #'(lambda (x)
	    (princ (format "%s [label =\"%s\", shape = \"box\"];\n"
			   (first x) (second x)))) table)
(princ (format "%s -> %s;\n" (first (first table)) (first (second table))))
a [label ="Hello", shape = "box"];
b [label ="World", shape = "box"];
a -> b;
digraph {
 $input
}

test-dot.png

digraph G {
    main -> parse -> execute;
    main -> init;
    main -> cleanup;
    execute -> make_string;
    execute -> printf
    init -> make_string;
    main -> printf;
    execute -> compare;
}

func-call.png

digraph G {
    size ="4,4";
    main [shape=box];   /* this is a comment */
    main -> parse [weight=8];
    parse -> execute;
    main -> init [style=dotted];
    main -> cleanup;
    execute -> { make_string; printf}
    init -> make_string;
    edge [color=red];   // so is this
    main -> printf [style=bold,label="100 times"];
    make_string [label="make a\nstring"];
    node [shape=box,style=filled,color=".7 .3 1.0"];
    execute -> compare;
}

fancy-func-call.png

digraph G {
     a -> b -> c;
     b -> d;
     a [shape=polygon,sides=5,peripheries=3,color=lightblue,style=filled];
     c [shape=polygon,sides=4,skew=.4,label="hello world"]
     d [shape=invtriangle];
     e [shape=polygon,sides=4,distortion=.7];
}

shape-polygon.png

digraph structs {
node [shape=record];
     struct1 [shape=record,label="<f0> left|<f1> mid\ dle|<f2> right"];
     struct2 [shape=record,label="<f0> one|<f1> two"];
     struct3 [shape=record,label="hello\nworld |{ b |{c|<here> d|e}| f}| g | h"];
     struct1 -> struct2;
     struct1 -> struct3;
}

shape-record.png

digraph html {
      abc [shape=none, margin=0, label=<
  <TABLE BORDER="0" CELLBORDER="1" CELLSPACING="0" CELLPADDING="4">
  <TR><TD ROWSPAN="3"><FONT COLOR="red">hello</FONT><BR/>world</TD>
      <TD COLSPAN="3">b</TD>
      <TD ROWSPAN="3" BGCOLOR="lightgrey">g</TD>
      <TD ROWSPAN="3">h</TD>
  </TR>
  <TR><TD>c</TD>
      <TD PORT="here">d</TD>
      <TD>e</TD>
  </TR>
  <TR><TD COLSPAN="3">f</TD>
  </TR>
  </TABLE>>];
}

label-html.png

digraph g {
    node [shape = record,height=.1];
    node0[label = "<f0> |<f1> G|<f2> "];
    node1[label = "<f0> |<f1> E|<f2> "];
    node2[label = "<f0> |<f1> B|<f2> "];
    node3[label = "<f0> |<f1> F|<f2> "];
    node4[label = "<f0> |<f1> R|<f2> "];
    node5[label = "<f0> |<f1> H|<f2> "];
    node6[label = "<f0> |<f1> Y|<f2> "];
    node7[label = "<f0> |<f1> A|<f2> "];
    node8[label = "<f0> |<f1> C|<f2> "];
    "node0":f2 -> "node4":f1;
    "node0":f0 -> "node1":f1;
    "node1":f0 -> "node2":f1;
    "node1":f2 -> "node3":f1;
    "node2":f2 -> "node8":f1;
    "node2":f0 -> "node7":f1;
    "node4":f2 -> "node6":f1;
    "node4":f0 -> "node5":f1;
}

node-ports.png

digraph structs {
     node [shape=record];
     struct1 [shape=record,label="<f0> left|<f1> middle|<f2> right"];
     struct2 [shape=record,label="<f0> one|<f1> two"];
     struct3 [shape=record,label="hello\nworld |{ b |{c|<here> d|e}| f}| g | h"];
     struct1:f1 -> struct2:f0;
     struct1:f2 -> struct3:here;
}

node-ports-struct.png

digraph G {
    nodesep=.05;
    rankdir=LR;
    node [shape=record,width=.1,height=.1];

    node0 [label = "<f0> |<f1> |<f2> |<f3> |<f4> |<f5> |<f6> | ",height=2.5];
    node [width = 1.5];
    node1 [label = "{<n> n14 | 719 |<p> }"];
    node2 [label = "{<n> a1  | 805 |<p> }"];
    node3 [label = "{<n> i9  | 718 |<p> }"];
    node4 [label = "{<n> e5  | 989 |<p> }"];
    node5 [label = "{<n> t20 | 959 |<p> }"];
    node6 [label = "{<n> o15 | 794 |<p> }"];
    node7 [label = "{<n> s19 | 659 |<p> }"];

    node0:f0 -> node1:n;
    node0:f1 -> node2:n;
    node0:f2 -> node3:n;
    node0:f5 -> node4:n;
    node0:f6 -> node5:n;
    node2:p -> node6:n;
    node4:p -> node7:n;
}

node-ports-hash.png

digraph G {
  subgraph cluster0 {
    node [style=filled,color=white];
    style=filled;
    color=lightgrey;
    a0 -> a1 -> a2 ->a3;
    label = "process #1";
  }

  subgraph cluster1 {
    node [style=filled];
    b0 -> b1 -> b2 ->b3;
    label = "process #1";
    color=blue;
  }

  start -> a0;
  start -> b0;
  a1 -> b3;
  b2 -> a3;
  a3 -> a0;
  a3 -> end;
  b3 -> end;

  start [shape=Mdiamond];
  end [shape=Msquare];
}

cluster.png

digraph G {
  size="8,6"; ratio=fill; node[fontsize=24];

  ciafan->computefan; fan->increment; computefan->fan; stringdup->fatal;
  main->exit; main->interp_err; main->ciafan; main->fatal; main->malloc;
  main->strcpy; main->getopt; main->init_index; main->strlen; fan->fatal;
  fan->ref; fan->interp_err; ciafan->def; fan->free; computefan->stdprintf;
  computefan->get_sym_fields; fan->exit; fan->malloc; increment->strcmp;
  computefan->malloc; fan->stdsprintf; fan->strlen; computefan->strcmp;
  computefan->realloc; computefan->strlen; debug->sfprintf; debug->strcat;
  stringdup->malloc; fatal->sfprintf; stringdup->strcpy; stringdup->strlen;
  fatal->exit;

  subgraph "cluster_error.h" { label="error.h"; interp_err; }

  subgraph "cluster_sfio.h" { label="sfio.h"; sfprintf; }

  subgraph "cluster_ciafan.c" { label="ciafan.c"; ciafan; computefan; increment; }

  subgraph "cluster_util.c" { label="util.c"; stringdup; fatal; debug; }

  subgraph "cluster_query.h" { label="query.h"; ref; def; }

  subgraph "cluster_field.h" { get_sym_fields; }

  subgraph "cluster_stdio.h" { label="stdio.h"; stdprintf; stdsprintf; }

  subgraph "cluster_<libc.a>" { getopt; }

  subgraph "cluster_stdlib.h" { label="stdlib.h"; exit; malloc; free; realloc; }

  subgraph "cluster_main.c" { main; }

  subgraph "cluster_index.h" { init_index; }

  subgraph "cluster_string.h" { label="string.h"; strcpy; strlen; strcmp; strcat; }
}

call-graph-with-labeled-cluster.png

digraph G {
  compound = true;
  subgraph cluster0 {
    a -> b;
    a -> c;
    b -> d;
    c -> d;
  }
  subgraph cluster1 {
    e -> g;
    e -> f;
  }
  b -> f [lhead=cluster1];
  d -> e;
  c -> g [ltail=cluster0,
	  lhead=cluster1];
  c -> e [ltail=cluster0];
  d -> h;
}

graph-with-edges-cluster.png

digraph world {
  size="7,7";
  {rank=same; S8 S24 S1 S35 S30;}
  {rank=same; T8 T24 T1 T35 T30;}
  {rank=same; 43 37 36 10 2;}
  {rank=same; 25 9 38 40 13 17 12 18;}
  {rank=same; 26 42 11 3 33 19 39 14 16;}
  {rank=same; 4 31 34 21 41 28 20;}
  {rank=same; 27 5 22 32 29 15;}
  {rank=same; 6 23;}
  {rank=same; 7;}

  S8 -> 9;
  S24 -> 25;
  S24 -> 27;
  S1 -> 2;
  S1 -> 10;
  S35 -> 43;
  S35 -> 36;
  S30 -> 31;
  S30 -> 33;
  9 -> 42;
  9 -> T1;
  25 -> T1;
  25 -> 26;
  27 -> T24;
  2 -> {3 ; 16 ; 17 ; T1 ; 18}
  10 -> { 11 ; 14 ; T1 ; 13; 12;}
  31 -> T1;
  31 -> 32;
  33 -> T30;
  33 -> 34;
  42 -> 4;
  26 -> 4;
  3 -> 4;
  16 -> 15;
  17 -> 19;
  18 -> 29;
  11 -> 4;
  14 -> 15;
  37 -> {39 ; 41 ; 38 ; 40;}
  13 -> 19;
  12 -> 29;
  43 -> 38;
  43 -> 40;
  36 -> 19;
  32 -> 23;
  34 -> 29;
  39 -> 15;
  41 -> 29;
  38 -> 4;
  40 -> 19;
  4 -> 5;
  19 -> {21 ; 20 ; 28;}
  5 -> {6 ; T35 ; 23;}
  21 -> 22;
  20 -> 15;
  28 -> 29;
  6 -> 7;
  15 -> T1;
  22 -> T35;
  22 -> 23;
  29 -> T30;
  7 -> T8;
  23 -> T24;
  23 -> T1;
}

graph-with-edges-cluster.png

digraph G {
  size="8,6"; ratio=fill; node[fontsize=24];
  a0 -> a1; a0 -> a2; a1 -> a3; a2 -> a3; a2 -> a4; a3 -> a5; a4 -> a5;

  subgraph "cluster0" {
     label="scb_0";
     a0; a3; a1; a2;
  }

  subgraph "cluster1" {
     label="scb_1";
     a4;
  }

  subgraph "cluster2" {
     label="scb_2";
     a5;
  }

}
[[https://brantou.github.io/images/ob-dot-intro/graph-with-scb.png]]
Last Updated 2018-04-26 Thu 18:43.
Render by hexo-renderer-org with Emacs 25.3.2 (Org mode 8.2.10)

Strings, bytes, runes and characters in Go

发表于 2018-04-03 | 分类于 技术积累 |

1 Printing strings

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
package main

import "fmt"

func main() {
const sample = "\xbd\xb2\x3d\xbc\x20\xe2\x8c\x98"

fmt.Println("Println:")
fmt.Println(sample)

fmt.Println("Byte loop:")
for i := 0; i < len(sample); i++ {
fmt.Printf("%x ", sample[i])
}
fmt.Printf("\n")

fmt.Println("Printf with %x:")
fmt.Printf("%x\n", sample)

fmt.Println("Printf with % x:")
fmt.Printf("% x\n", sample)

fmt.Println("Printf with %q:")
fmt.Printf("%q\n", sample)

fmt.Println("Printf with %+q:")
fmt.Printf("%+q\n", sample)

fmt.Println("Byte loop with %q:")
for i := 0; i < len(sample); i++ {
fmt.Printf("%q ", sample[i])
}
fmt.Printf("\n")
}

2 UTF-8 and string literals

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
package main

import "fmt"

func main() {
const placeOfInterest = `⌘`

fmt.Printf("plain string: ")
fmt.Printf("%s", placeOfInterest)
fmt.Printf("\n")

fmt.Printf("quoted string: ")
fmt.Printf("%+q", placeOfInterest)
fmt.Printf("\n")

fmt.Printf("hex bytes: ")
for i := 0; i < len(placeOfInterest); i++ {
fmt.Printf("%x ", placeOfInterest[i])
}
fmt.Printf("\n")
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
package main

import "fmt"

func main() {
const nihongo = "日本語"
for index, runeValue := range nihongo {
fmt.Printf("%#U starts at byte position %d\n", runeValue, index)
}

const str = "abc"
for index, runeValue := range str {
fmt.Printf("%#U starts at byte position %d\n", runeValue, index)
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
package main

import (
"fmt"
"unicode/utf8"
)

func main() {
const nihongo = "日本語"
for i, w := 0, 0; i < len(nihongo); i += w {
runeValue, width := utf8.DecodeRuneInString(nihongo[i:])
fmt.Printf("%#U starts at byte position %d\n", runeValue, i)
w = width
}
}
Last Updated 2018-04-08 Sun 18:24.
Render by hexo-renderer-org with Emacs 25.3.2 (Org mode 8.2.10)

Leetcode-greedy

发表于 2018-03-29 | 分类于 技术积累 |

1 DONE 分发饼干

  • State "DONE" from "TODO" [2018-03-29 四 15:45]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
import "sort"

func findContentChildren(g []int, s []int) int {
sort.Ints(g)
sort.Ints(s)
var ans, gi int
for i, _ := range s {
for j := gi; j < len(g); j += 1 {
if g[j] <= s[i] {
gi = j + 1
ans += 1
break
}
}
}

return ans
}

2 DONE 分配糖果

  • State "DONE" from "TODO" [2018-03-30 五 17:52]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
func max(a, b int) int {
if a > b {
return a
} else {
return b
}
}

func candy(ratings []int) int {
if len(ratings) == 0 {
return 0
}
if len(ratings) == 1 {
return 1
}

candys := make([]int, len(ratings))
candyHelper(ratings, candys, 0, len(candys))
ans := 0
for i, _ := range candys {
ans += candys[i]
}

return ans
}

func candyHelper(ratings, candys []int, start, end int) {
if start >= end {
return
}

ti := start
tn := 0
for i := start + 1; i < end; i += 1 {
if ratings[i] == ratings[ti] && ti+tn+1 == i {
tn += 1
continue
}

if ratings[i] < ratings[ti] {
ti = i
tn = 0
}
}

var cs, ce int
if ti > start && ti+tn < end-1 {
cs, ce = 1, 1
} else if ti == start && ti+tn == end-1 {
if start > 0 && end < len(ratings) {
cs, ce = candys[start-1]+1, candys[end]+1
} else if start == 0 && end == len(ratings) {
cs, ce = 1, 1
} else if start == 0 {
cs, ce = 1, candys[end]+1
} else if end == len(ratings) {
cs, ce = candys[start-1]+1, 1
}
} else if ti == start {
if start > 0 {
cs = candys[start-1] + 1
} else {
cs = 1
}
ce = 1
} else if ti+tn == end-1 {
if end < len(ratings) {
ce = candys[end] + 1
} else {
ce = 1
}
cs = 1
}

if tn == 0 {
candys[ti] = max(cs, ce)
} else {
candys[ti], candys[ti+tn] = cs, ce
for i := 1; i < tn; i += 1 {
candys[ti+i] = 1
}
}

candyHelper(ratings, candys, start, ti)
candyHelper(ratings, candys, ti+tn+1, end)
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
package main

import "fmt"



func main() {
fmt.Println(candy([]int{2, 1, 3, 1}))
fmt.Println(candy([]int{2, 1, 3, 1, 4, 5}))
fmt.Println(candy([]int{2}))
fmt.Println(candy([]int{2, 1 }))
fmt.Println(candy([]int{1, 2 }))
fmt.Println(candy([]int{3,2,1}))
fmt.Println(candy([]int{1,2,3}))
fmt.Println(candy([]int{2,2,1}))
fmt.Println(candy([]int{2,1,1}))
fmt.Println(candy([]int{2,2}))
fmt.Println(candy([]int{2,1,1,2}))
fmt.Println(candy([]int{2,1,1,1,3}))
fmt.Println(candy([]int{1,2,2}))
}

3 DONE 通配符匹配

  • State "DONE" from "TODO" [2018-04-02 一 15:50]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
import "strings"

func isMatch(s string, p string) bool {
for strings.Contains(p, "**") {
p = strings.Replace(p, "**", "*", -1)
}

return match(s, p)
}

func match(s string, p string) bool {
if len(s) == 0 && len(p) == 0 {
return true
}

if len(p) == 0 && len(s) > 0 {
return false
}

if len(s) == 0 {
for i, _ := range p {
if p[i:i+1] != "*" {
return false
}
}
return true
}

if p[0:1] == "?" || p[0] == s[0] {
return match(s[1:], p[1:])
}

if p[0:1] == "*" {
return match(s, p[1:]) || isMatch(s[1:], p)
}

return false
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
func isMatch(s string, p string) bool {
slen, plen := len(s), len(p)
i, j := 0, 0
is, ip := -1, -1
for i < slen {
if j == plen {
if ip == -1 {
return false
} else {
is += 1
i = is
j = ip + 1
}
continue
}

if p[j:j+1] == "*" {
is = i
ip = j
j += 1
} else {
if s[i] == p[j] || p[j:j+1] == "?" {
i += 1
j += 1
} else if ip == -1 {
return false
} else {
is += 1
i = is
j = ip + 1
}
}
}

for j < plen && p[j:j+1] == "*" {
j += 1
}

return j == plen
}

4 DONE 拼接最大数

  • State "DONE" from "TODO" [2018-04-03 二 14:31]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
func maxNumber(nums1 []int, nums2 []int, k int) []int {
if k < 1 {
return []int{}
}
if len(nums2) > len(nums1) {
nums1, nums2 = nums2, nums1
}

num := nums1[0]
ai := 0
ni := 0
prev_ai := 1
for i := 0; i < len(nums1); i += 1 {
if len(nums1)+len(nums2)-i < k {
break
}

if nums1[i] > num {
prev_ai = ai
num = nums1[i]
ai, ni = 0, i
}

if nums1[i] == num {
if 0 != prev_ai && ai != 0 {
num = nums1[i]
ai, ni = 0, i
}
}

for j := 0; j < len(nums2); j += 1 {
if len(nums1)+len(nums2)-(i+j) < k {
break
}

if nums2[j] > num {
prev_ai = ai
num = nums2[j]
ai, ni = 1, j
}

if nums2[j] == num {
if 1 != prev_ai && ai != 1 {
num = nums2[j]
ai, ni = 1, j
}
}
}
}

ans := []int{num}
if ai == 0 {
return append(ans, maxNumber(nums1[ni+1:], nums2, k-1)...)
} else {
return append(ans, maxNumber(nums1, nums2[ni+1:], k-1)...)
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
func maxNumber(nums1 []int, nums2 []int, k int) []int {
ans := make([]int, k)
len1, len2 := len(nums1), len(nums2)
for i := max(k-len2, 0); i <= min(k, len1); i += 1 {
ans = maxInts(ans, merge(getMax(nums1, i), getMax(nums2, k-i)))
}

return ans
}

func getMax(nums []int, k int) []int {
ans := make([]int, 0)
drop := len(nums) - k
for i := 0; i < len(nums); i += 1 {
for drop > 0 && len(ans) > 0 && nums[i] > ans[len(ans)-1] {
drop -= 1
ans = ans[:len(ans)-1]
}
ans = append(ans, nums[i])
}

return ans[:k]
}

func merge(lnums []int, rnums []int) []int {
ans := make([]int, 0, len(lnums)+len(rnums))
li, ri := 0, 0
ll, lr := len(lnums), len(rnums)
for li < ll && ri < lr {
if lnums[li] > rnums[ri] {
ans = append(ans, lnums[li])
li += 1
} else if lnums[li] < rnums[ri] {
ans = append(ans, rnums[ri])
ri += 1
} else {
if isMaxInts(lnums[li:], rnums[ri:]) {
ans = append(ans, lnums[li])
li += 1
} else {
ans = append(ans, rnums[ri])
ri += 1
}
}
}

if li < ll {
ans = append(ans, lnums[li:]...)
}
if ri < lr {
ans = append(ans, rnums[ri:]...)
}

return ans
}

func maxInts(lnums []int, rnums []int) []int {
i := 0
ll, lr := len(lnums), len(rnums)
for i < ll && i < lr {
if lnums[i] > rnums[i] {
return lnums
}

if lnums[i] < rnums[i] {
return rnums
}

i += 1
}

if i == ll && i == lr {
return lnums
} else if i < ll {
return lnums
} else {
return rnums
}
}

func isMaxInts(lnums, rnums []int) bool {
i := 0
ll, lr := len(lnums), len(rnums)
for i < ll && i < lr {
if lnums[i] > rnums[i] {
return true
}

if lnums[i] < rnums[i] {
return false
}

i += 1
}

if i == ll && i == lr {
return true
} else if i < ll {
return true
} else {
return false
}
}

func max(a, b int) int {
if a > b {
return a
} else {
return b
}
}

func min(a, b int) int {
if a < b {
return a
} else {
return b
}
}
1
2
3
4
5
6
7
8
9
10
11
package main

import "fmt"



func main() {
fmt.Println(maxNumber([]int{3, 4, 6, 5}, []int{9, 1, 2, 5, 8, 3}, 5))
fmt.Println(maxNumber([]int{6, 7}, []int{6, 0, 4}, 5))
fmt.Println(maxNumber([]int{3, 9}, []int{8, 9}, 3))
}

5 DONE 去除重复字母

  • State "DONE" from "TODO" [2018-04-03 二 16:36]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
func removeDuplicateLetters(s string) string {
sM := make(map[string]int)
for i := 0; i < len(s); i += 1 {
sM[s[i:i+1]] += 1
}

var ans string
drop := len(s) - len(sM)
eM := make(map[string]bool)
for i := 0; i < len(s); i += 1 {
if eM[s[i:i+1]] {
drop -= 1
sM[s[i:i+1]] -= 1
continue
}

for drop > 0 && len(ans) > 0 && s[i:i+1] <= ans[len(ans)-1:] && sM[ans[len(ans)-1:]] > 1 {

drop -= 1
sM[ans[len(ans)-1:]] -= 1
eM[ans[len(ans)-1:]] = false
ans = ans[:len(ans)-1]
}
ans += s[i : i+1]
eM[s[i:i+1]] = true
}

return ans[:len(sM)]
}
1
2
3
4
5
6
7
8
9
10
11
12
package main

import "fmt"



func main() {
fmt.Println(removeDuplicateLetters("bcabc"))
fmt.Println(removeDuplicateLetters("cbacdcbc"))
fmt.Println(removeDuplicateLetters("ccacbaba"))
fmt.Println(removeDuplicateLetters("rusrbofeggbbkyuyjsrzornpdguwzizqszpbicdquakqws"))
}

6 DONE 跳跃游戏 II

  • State "DONE" from "TODO" [2018-04-03 二 17:17]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
func jump(nums []int) int {
if len(nums) < 2 {
return 0
}

dp := make([]int, len(nums))
dp[0] = 0
for i := 1; i < len(nums); i += 1 {
dp[i] = len(nums)
for j := i-1; j >= 0; j -= 1 {
if nums[j] >= i-j {
dp[i] = min(dp[i], dp[j]+1)
}
}
}

return dp[len(dp)-1]
}

func min(a, b int) int {
if a < b {
return a
} else {
return b
}
}
1
2
3
4
5
6
7
8
9
package main

import "fmt"



func main() {
fmt.Println(jump([]int{2, 3, 1, 1, 4}))
}

7 DONE 设置交集大小至少为2

  • State "DONE" from "TODO" [2018-04-04 三 13:39]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
func intersectionSizeTwo(intervals [][]int) int {
sort.Slice(intervals,
func(i, j int) bool {
return intervals[i][1] < intervals[j][1] ||
intervals[i][1] == intervals[j][1] && intervals[i][0] < intervals[j][0]
})

new_intervals := make([][]int, 0)
left := intervals[0][0]
right := intervals[0][1]
for i := 1; i < len(intervals); i += 1 {
interval := intervals[i]
if interval[1] == right {
left = interval[0]
} else if interval[0] > left {
new_intervals = append(new_intervals, []int{left, right})
left = interval[0]
right = interval[1]
}
}
new_intervals = append(new_intervals, []int{left, right})
fmt.Println(new_intervals)

first := new_intervals[0][1] - 1
second := first + 1
ans := 2
for i := 1; i < len(new_intervals); i += 1 {
interval := new_intervals[i]
if interval[0] > second {
ans += 2
first = interval[1] - 1
second = first + 1
} else if interval[0] > first {
ans += 1
first = second
second = interval[1]
}
}

return ans
}

8 DONE Course Schedule III

  • State "DONE" from "TODO" [2018-04-04 三 17:02]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
type IntHeap []int

func (h IntHeap) Len() int { return len(h) }
func (h IntHeap) Less(i, j int) bool { return h[i] > h[j] }
func (h IntHeap) Swap(i, j int) { h[i], h[j] = h[j], h[i] }

func (h *IntHeap) Push(x interface{}) {
*h = append(*h, x.(int))
}

func (h *IntHeap) Pop() interface{} {
old := *h
n := len(old)
x := old[n-1]
*h = old[0 : n-1]
return x
}

func scheduleCourse(courses [][]int) int {
sort.Slice(courses,
func(i, j int) bool {
return courses[i][1] < courses[j][1] ||
courses[i][1] == courses[j][1] && courses[i][0] < courses[j][0]
})

h := &IntHeap{}
heap.Init(h)
curTime := 0
for i := 0; i < len(courses); i += 1 {
course := courses[i]
curTime += course[0]
heap.Push(h, course[0])
if curTime > course[1] {
curTime -= heap.Pop(h).(int)
}
}

return h.Len()
}
1
2
3
4
5
6
7
8
9
10
11
12
package main



func main() {
fmt.Println(scheduleCourse([][]int{
[]int{100, 200}, []int{200, 1300},
[]int{1000, 1250}, []int{2000, 3200}}))

fmt.Println(scheduleCourse([][]int{
[]int{5, 5}, []int{1, 2}, []int{2, 6}, []int{2,7}}))
}

9 DONE Patching Array

  • State "DONE" from "TODO" [2018-04-06 五 17:44]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
func minPatches(nums []int, n int) int {
miss, ans, i := 1, 0, 0
for miss <= n {
if i < len(nums) && nums[i] <= miss {
miss += nums[i]
i += 1
} else {
miss += miss
ans += 1
}
}

return ans
}

10 DONE Couples Holding Hands

  • State "DONE" from "TODO" [2018-04-07 六 22:05]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
func minSwapsCouples(row []int) int {
n, ans := len(row), 0
for i := 0; i < n; i += 2 {
var dest int
if row[i]%2 == 0 {
dest = row[i] + 1
} else {
dest = row[i] - 1
}

if row[i+1] == dest {
continue
}

ans += 1
for j := i + 2; j < n; j += 1 {
if row[j] == dest {
row[i+1], row[j] = row[j], rows[i+1]
break
}
}
}

return ans
}

11 DONE IPO

  • State "DONE" from "TODO" [2018-04-06 五 18:40]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
func findMaximizedCapital(k int, W int, Profits []int, Capital []int) int {
if k < 1 || len(Profits) < 1 {
return W
}

max_profit, index := -1, -1
for i := 0; i < len(Profits); i += 1 {
if Capital[i] <= W && Profits[i] > max_profit {
max_profit = Profits[i]
index = i
}
}

if index < 0 {
return W
}

return findMaximizedCapital(k-1, W+max_profit,
append(Profits[0:index], Profits[index+1:]...),
append(Capital[0:index], Capital[index+1:]...))
}
1
2
3
4
5
6
7
8
9
package main

import "fmt"



func main() {
fmt.Println(findMaximizedCapital(2, 0, []int{1, 2, 3}, []int{0, 1, 1}))
}
Last Updated 2018-04-25 Wed 22:17.
Render by hexo-renderer-org with Emacs 25.3.2 (Org mode 8.2.10)

基础算法和数据结构

发表于 2018-03-17 | 分类于 技术积累 |

1 DONE 排序

  • State "DONE" from "TODO" [2018-03-20 Tue 18:34]

1.1 DONE 两个有序数组合并

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
func merge(A, B []int) []int {
C := make([]int, 0)
a_i, b_i := 0, 0
for a_i < len(A) && b_i < len(B) {
if A[a_i] > B[b_i] {
C = append(C, B[b_i])
b_i += 1
} else if A[a_i] < B[b_i] {
C = append(C, A[a_i])
a_i += 1
} else {
C = append(C, A[a_i], B[b_i])
a_i += 1
b_i += 1
}
}

if a_i < len(A) {
C = append(C, A[a_i:]...)
}

if b_i < len(B) {
C = append(C, B[b_i:]...)
}

return C
}
1
2
3
4
5
6
7
8
9
10
11
package main

import "fmt"



func main() {
fmt.Println(merge([]int{1, 3, 5}, []int{2, 4, 6}))
fmt.Println(merge([]int{1, 3, 5, 7, 9}, []int{2, 4, 6}))
fmt.Println(merge([]int{1, 3, 5}, []int{2, 4, 6, 8, 10}))
}

1.2 DONE 插入排序

  • State "DONE" from "TODO" [2018-03-17 Sat 13:10]
1
2
3
4
5
6
7
8
9
10
11
func isort(nums []int) {
for i := 1; i < len(nums); i += 1 {
for j := i; j > 0; j -= 1 {
if nums[j-1] > nums[j] {
nums[j-1], nums[j] = nums[j], nums[j-1]
} else {
break
}
}
}
}
1
2
3
4
5
6
7
8
9
10
11
package main

import "fmt"



func main() {
nums := []int{2, 3, 6, 1, 5, 7, 9, 4}
isort(nums)
fmt.Println(nums)
}

1.3 DONE 二分排序

1
2
3
4
5
6
7
8
9
10
func bsort(nums []int) {
if len(nums) == 1 {
return
}

bsort(nums[0 : len(nums)/2])
bsort(nums[len(nums)/2:])

copy(nums, merge(nums[0:len(nums)/2], nums[len(nums)/2:]))
}
1
2
3
4
5
6
7
8
9
10
11
12
13
package main

import "fmt"





func main() {
nums := []int{2, 3, 5, 4, 1, 10, 7, 9, 8}
bsort(nums)
fmt.Println(nums)
}

1.4 DONE 快速排序

1
2
3
4
5
6
7
8
9
func qsort(nums []int) {
if len(nums) < 2 {
return
}

p := partition(nums)
qsort(nums[0:p])
qsort(nums[p+1:])
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
func partition(nums []int) int {
r := rand.Intn(len(nums))
nums[r], nums[0] = nums[0], nums[r]
mid := nums[0]
s, e := 0, len(nums)-1
for s < e {
for s < e && nums[e] >= mid {
e -= 1
}

if s < e {
nums[s] = nums[e]
}

for s < e && nums[s] <= mid {
s += 1
}

if s < e {
nums[e] = nums[s]
}
}
nums[s] = mid
return s
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
package main

import (
"fmt"
"math/rand"
)





func main() {
nums := []int{2, 8, 5, 4, 6, 10, 7, 9, 3}
qsort(nums)
fmt.Println(nums)
nums = []int{2, 8, 5, 7, 1, 10, 4, 9, 3}
qsort(nums)
fmt.Println(nums)
nums = []int{2, 8, 5, 7, 10, 11, 4, 9, 3}
qsort(nums)
fmt.Println(nums)
}

1.5 DONE 堆排序

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
func parent(i int) int {
return (i - 1) / 2
}

func left(i int) int {
return 2*i + 1
}

func right(i int) int {
return 2*i + 2
}

func heapDown(nums []int, start, end int) {
p := start
l := left(p)
for {
if l > end {
break
}

if l < end && nums[l] < nums[l+1] {
l += 1
}

if nums[p] >= nums[l] {
break
} else {
nums[l], nums[p] = nums[p], nums[l]
p = l
l = left(p)
}
}
}

func hsort(nums []int) {
for i := len(nums) / 2; i >= 0; i -= 1 {
heapDown(nums, i, len(nums)-1)
}

for i := len(nums) - 1; i > 0; i -= 1 {
nums[i], nums[0] = nums[0], nums[i]

heapDown(nums, 0, i-1)
}
}
1
2
3
4
5
6
7
8
9
10
11
package main

import "fmt"



func main() {
nums := []int{2, 4, 6, 3, 5, 7, 1, 10, 8, 9}
hsort(nums)
fmt.Println(nums)
}

1.6 DONE 计数排序

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
func countingSort(nums []int) []int {
max := nums[0]
for _, num := range nums {
if num > max {
max = num
}
}

ansArr := make([]int, len(nums))
countArr := make([]int, max+1)

for i := 0; i < len(nums); i += 1 {
countArr[nums[i]] += 1
}

for i := 1; i < len(countArr); i += 1 {
countArr[i] += countArr[i-1]
}

for i := len(nums) - 1; i >= 0; i -= 1 {
ansArr[countArr[nums[i]]-1] = nums[i]
countArr[nums[i]] -= 1
}

return ansArr
}
1
2
3
4
5
6
7
8
9
10
package main

import "fmt"



func main() {
nums := []int{2, 3, 5, 2, 3, 4, 8, 9, 7, 6, 8, 7, 5, 4, 6, 7}
fmt.Println(countingSort(nums))
}

1.7 DONE 基数排序

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
func radixSort(nums []int) []int {
max := nums[0]
for _, num := range nums {
if num > max {
max = num
}
}
d := 1
tmp_max := max
for tmp_max > 0 {
tmp_max /= 10
d += 1
}

for i := 0; i < d; i += 1 {
nums = countingSort(nums, i)
}

return nums
}

func countingSort(nums []int, d int) []int {
max := 9
ansArr := make([]int, len(nums))
countArr := make([]int, max+1)

for i := 0; i < len(nums); i += 1 {
countArr[getBit(nums[i], d)] += 1
}

for i := 1; i < len(countArr); i += 1 {
countArr[i] += countArr[i-1]
}

for i := len(nums) - 1; i >= 0; i -= 1 {
ansArr[countArr[getBit(nums[i], d)]-1] = nums[i]
countArr[getBit(nums[i], d)] -= 1
}

return ansArr
}

func getBit(num, d int) int {
for num != 0 && d > 0 {
num /= 10
d -= 1
}

return num % 10
}
1
2
3
4
5
6
7
8
9
10
package main

import "fmt"



func main() {
nums := []int{123, 336, 255, 298, 321, 49, 82, 93, 78, 65, 81, 73, 550, 425, 68, 72}
fmt.Println(radixSort(nums))
}

1.8 DONE 桶排序

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
type ListNode struct {
next *ListNode
num int
}

func insert(h *ListNode, val int) *ListNode {
newNode := &ListNode{num: val}
dummyNode := &ListNode{next: h}
pre := dummyNode
curr := h
for curr != nil && curr.num <= val {
pre = curr
curr = curr.next
}

newNode.next = curr
pre.next = newNode

return dummyNode.next
}

func merge(lh, rh *ListNode) *ListNode {
dummyNode := &ListNode{}
dummy := dummyNode
for lh != nil && rh != nil {
if lh.num <= rh.num {
dummy.next = lh
lh = lh.next
} else {
dummy.next = rh
rh = rh.next
}
dummy = dummy.next
}

if lh != nil {
dummy.next = lh
}
if rh != nil {
dummy.next = rh
}

return dummyNode.next
}

func BucketSort(nums []int, bucket_num int) {
buckets := make([]*ListNode, bucket_num)
for _, num := range nums {
i := num / bucket_num
h := buckets[i]
buckets[i] = insert(h, num)
}

h := buckets[0]
for i := 1; i < len(buckets); i += 1 {
h = merge(h, buckets[i])
}

for i := 0; i < len(buckets); i += 1 {
nums[i] = h.num
h = h.next
}

return
}
1
2
3
4
5
6
7
8
9
10
11
package main

import "fmt"



func main() {
nums := []int{22, 25, 11, 15, 33, 44, 55, 66, 77, 88, 99}
BucketSort(nums, 10)
fmt.Println(nums)
}

2 DONE 查找

2.1 DONE 二分查找

  • State "DONE" from "TODO" [2018-03-27 Tue 11:28]

2.1.1 DONE 递归

  • State "DONE" from "TODO" [2018-03-27 Tue 11:28]
1
2
3
4
5
6
7
8
9
10
11
12
13
func binarySearch(nums []int, start, end, target int) int {
if start > end {
return -1
}
mid := start + (end-start)/2
if nums[mid] > target {
return binarySearch(nums, start, mid-1, target)
} else if nums[mid] < target {
return binarySearch(nums, mid+1, end, target)
} else {
return mid
}
}

2.1.2 DONE 非递归

  • State "DONE" from "TODO" [2018-03-27 Tue 11:28]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
func binarySearch(nums []int, start, end, target int) int {
for {
if start > end {
return -1
}

mid := start + (end-start)/2
if nums[mid] > target {
end = mid - 1
} else if nums[mid] < target {
start = mid + 1
} else {
return mid
}
}
}

2.2 DONE 插值查找

  • State "DONE" from "TODO" [2018-03-27 Tue 11:24]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
func interpolationSearch(nums []int, start, end, target int) int {
if start > end {
return -1
}

mid := start + (target-nums[start])/(nums[end]-nums[start])*(end-start)
if nums[mid] > target {
return interpolationSearch(nums, start, mid-1, target)
} else if nums[mid] < target {
return interpolationSearch(nums, mid+1, end, target)
} else {
return mid
}
}

2.3 DONE 斐波那契查找

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
package main

import "fmt"

type FibonacciFunc func(int) int

func GenFibonacciFunc(size int) FibonacciFunc {
if size < 2 {
size = 2
}
capacity := 20
nums := make([]int, size, capacity)
nums[0] = 0
nums[1] = 1
for i := 2; i < len(nums); i += 1 {
nums[i] = nums[i-1] + nums[i-2]
}

return func(index int) int {
if len(nums) > index {
return nums[index]
}

csize := len(nums)
for csize <= index {
nums = append(nums, nums[csize-1]+nums[csize-2])
csize += 1
}

return nums[index]
}
}

func fibonacciSearch(nums []int, target int) int {
fibFunc := GenFibonacciFunc(10)
size := len(nums)
start, end := 0, size-1
fi := 0
for {
if size > fibFunc(fi) {
fi += 1
} else {
break
}
}

for {
if start > end {
return -1
}

// adjust fi
for start+fibFunc(fi-1)-1 > end {
fi -= 1
}
mid := start + fibFunc(fi-1) - 1

if target < nums[mid] {
end = mid - 1
fi -= 1
} else if target > nums[mid] {
start = mid + 1
fi -= 2
} else {
return mid
}
}
}

func main() {
nums := []int{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}
fmt.Println(fibonacciSearch(nums, 1))
fmt.Println(fibonacciSearch(nums, 10))
fmt.Println(fibonacciSearch(nums, 5))
fmt.Println(fibonacciSearch(nums, 15))
}

2.4 DONE 字符串暴力匹配

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
func violenMatch(s, p string) bool {
sLen, pLen := len(s), len(p)
si, pi := 0, 0
for si < sLen && pi < pLen {
if s[si] == p[pi] {
si += 1
pi += 1
} else {
si = si - pi + 1
pi = 0
}
}

if pi == pLen {
return true
} else {
return false
}
}
1
2
3
4
5
6
7
8
9
package main

import "fmt"



func main() {
fmt.Println(violenMatch("BBC ABCDAB ABCDABCDABDE", "ABCDABD"))
}

2.5 DONE KMP算法

假设现在文本串S匹配到 i 位置,模式串P匹配到 j 位置:

  • 如果j = -1,或者当前字符匹配成功(即S[i] == P[j]),都令i++,j++,继续匹配下一个字符
  • 如果j != -1,且当前字符匹配失败(即S[i] != P[j]),则令 i 不变,j = next[j]。 此举意味着失配时,模式串P相对于文本串S向右移动了 j-next[j] 位
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
func getNext(p string) []int {
pLen := len(p)
next := make([]int, pLen)
next[0] = -1

k, j := -1, 0
for j < pLen-1 {
if k == -1 || p[j] == p[k] {
k += 1
j += 1
next[j] = k
} else {
k = next[k]
}
fmt.Println(next, j, k)
}

return next
}

func kmpMatch(s, p string) bool {
next := getNext(p)

sLen := len(s)
pLen := len(p)

i, j := 0, 0
for i < sLen && j < pLen {
if j == -1 || s[i] == p[j] {
i += 1
j += 1
} else {
j = next[j]
}
}

if j == pLen {
return true
} else {
return false
}
}
1
2
3
4
5
6
7
8
9
package main

import "fmt"



func main() {
fmt.Println(kmpMatch("BBC ABCDAB ABCDABCDABDE", "CDABCDABD"))
}

3 DONE 链表

  • State "DONE" from "TODO" [2018-03-26 Mon 17:27]

3.1 DONE 单向链表

  • State "DONE" from "TODO" [2018-03-22 Thu 22:19]
    1
    2
    3
    4
    type ListNode struct {
    Val int
    Next *ListNode
    }
    1
    2
    3
    4
    5
    struct ListNode {
    int val;
    ListNode *next;
    ListNode(int x) : val(x), next(NULL) {}
    };

3.1.1 DONE Rotate List

  • State "DONE" from "FIXED" [2018-03-22 Thu 15:04]
  • State "FIXED" from "TODO" [2018-03-22 Thu 15:04]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
func rotateRight(head *ListNode, k int) *ListNode {
size := 0
curr := head
for curr != nil {
curr = curr.Next
size += 1
}
if size == 0 {
return head
}

k = k % size
if k == 0 {
return head
}

index := size - k - 1
curr = head
for index > 0 {
curr = curr.Next
index -= 1
}

nh := curr.Next
curr.Next = nil

curr = nh
for curr.Next != nil {
curr = curr.Next
}
curr.Next = head

return nh
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
package main

import "fmt"





func main() {
head := &ListNode{
Val: 1,
Next: &ListNode{
Val: 2,
Next: &ListNode{
Val: 3,
},
},
}

head = rotateRight(head, 1)
curr:= head
for curr != nil {
fmt.Println(curr.Val)
curr = curr.Next
}
}

3.1.2 DONE Reverse Linked List

  • State "DONE" from "TODO" [2018-03-22 Thu 16:18]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
func reverseList(head *ListNode) *ListNode {
if head == nil {
return head
}

dummyNode := &ListNode{Next: head}
pre := head
curr := head.Next
head.Next = nil
for curr != nil {
pre = curr
curr = curr.Next

pre.Next = dummyNode.Next
dummyNode.Next = pre
}

return dummyNode.Next
}

3.1.3 DONE Delete Node in a Linked List

  • State "DONE" from "TODO" [2018-03-22 Thu 16:52]
1
2
3
4
5
6
7
8
class Solution {
public:
void deleteNode(ListNode* node) {
auto next = node->next;
*node = *next;
delete next;
}
};

3.1.4 DONE Merge Two Sorted Lists

  • State "DONE" from "TODO" [2018-03-22 Thu 17:40]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
func mergeTwoLists(l1 *ListNode, l2 *ListNode) *ListNode {
dummyNode := &ListNode{}
dummy := dummyNode

for l1 != nil && l2 != nil {
if l1.Val < l2.Val {
dummy.Next = l1
l1 = l1.Next
} else {
dummy.Next = l2
l2 = l2.Next
}
dummy = dummy.Next
}

if l1 != nil {
dummy.Next = l1
}
if l2 != nil {
dummy.Next = l2
}

return dummyNode.Next
}

3.1.5 DONE Linked List Cycle

  • State "DONE" from "TODO" [2018-03-22 Thu 18:03]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
class Solution {
public:
bool hasCycle(ListNode *head) {
if (head == NULL || head->next == NULL) {
return false;
}

auto lp = head->next;
auto rp = head->next->next;

while (lp != NULL && rp != NULL) {
if (lp == rp) {
return true;
}

lp = lp->next;
if (rp->next == NULL) {
return false;
}
rp = rp->next->next;
}

return false;
}
};

3.1.6 DONE Linked List Cycle II

  • State "DONE" from "TODO" [2018-03-22 Thu 22:18]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
class Solution {
public:
ListNode *detectCycle(ListNode *head) {
if (head == NULL || head->next == NULL) {
return NULL;
}

auto lp = head->next;
auto rp = head->next->next;

while (lp != NULL && rp != NULL) {
if (lp == rp) {
break;
}

lp = lp->next;
if (rp->next == NULL) {
return NULL;
}
rp = rp->next->next;
}

if (lp != rp) {
return NULL;
}

int cl = 1;
rp = rp->next;
while (lp != rp) {
rp = rp->next;
cl += 1;
}

lp = head;
rp = head;
while (cl > 0) {
lp = lp->next;
cl -= 1;
}

while (lp != rp) {
lp = lp->next;
rp = rp->next;
}

return rp;
}
};

3.1.7 DONE 合并K个元素的有序链表

  • State "DONE" from "TODO" [2018-04-08 Sun 11:38]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
import (
"container/heap"
)

type ListNode struct {
Val int
Next *ListNode
}

type MyMinHeap []*ListNode

func (h MyMinHeap) Len() int { return len(h) }
func (h MyMinHeap) Less(i, j int) bool { return h[i].Val < h[j].Val }
func (h MyMinHeap) Swap(i, j int) { h[i], h[j] = h[j], h[i] }

func (h *MyMinHeap) Push(e interface{}) {
*h = append(*h, e.(*ListNode))
}

func (h *MyMinHeap) Pop() interface{} {
old := *h
n := len(old)
e := old[n-1]
*h = old[0 : n-1]
return e
}

func mergeKLists(lists []*ListNode) *ListNode {
h := &MyMinHeap{}
head := &ListNode{}
dummyNode := head
for i := 0; i < len(lists); i += 1 {
if lists[i] != nil {
heap.Push(h, lists[i])
}
}

for h.Len() > 0 {
n := heap.Pop(h).(*ListNode)
if n.Next != nil {
heap.Push(h, n.Next)
}
dummyNode.Next = n
dummyNode = dummyNode.Next
}

return head.Next
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
func mergeTwoLists(l1 *ListNode, l2 *ListNode) *ListNode {
dummyNode := &ListNode{}
dummy := dummyNode

for l1 != nil && l2 != nil {
if l1.Val < l2.Val {
dummy.Next = l1
l1 = l1.Next
} else {
dummy.Next = l2
l2 = l2.Next
}
dummy = dummy.Next
}

if l1 != nil {
dummy.Next = l1
}
if l2 != nil {
dummy.Next = l2
}

return dummyNode.Next
}

func mergeKLists(lists []*ListNode) *ListNode {
if len(lists) < 1 {
return nil
}

head := lists[0]
for i := 1; i < len(lists); i += 1 {
head = mergeTwoLists(head, lists[i])
}

return head
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
func mergeTwoLists(l1 *ListNode, l2 *ListNode) *ListNode {
dummyNode := &ListNode{}
dummy := dummyNode

for l1 != nil && l2 != nil {
if l1.Val < l2.Val {
dummy.Next = l1
l1 = l1.Next
} else {
dummy.Next = l2
l2 = l2.Next
}
dummy = dummy.Next
}

if l1 != nil {
dummy.Next = l1
}
if l2 != nil {
dummy.Next = l2
}

return dummyNode.Next
}

func mergeKLists(lists []*ListNode) *ListNode {
if len(lists) == 2 {
return mergeTwoLists(lists[0], lists[1])
} else if len(lists) == 1 {
return lists[0]
} else if len(lists) == 0 {
return nil
}

ll := mergeKLists(lists[:len(lists)/2])
rl := mergeKLists(lists[len(lists)/2:])

return mergeTwoLists(ll, rl)
}

3.1.8 DONE 每k个一组翻转链表

  • State "DONE" from "TODO" [2018-04-08 Sun 14:49]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
func reverseKGroup(head *ListNode, k int) *ListNode {
if head == nil || k < 2 {
return head
}

dummyNode := &ListNode{Next: head}
kg_dummyNode := dummyNode
kg_pre := kg_dummyNode.Next
kg_curr := kg_pre.Next
kg_tail := kg_pre

cn := k - 1
for kg_curr != nil {
kg_pre = kg_curr
kg_curr = kg_curr.Next

kg_pre.Next = kg_dummyNode.Next
kg_dummyNode.Next = kg_pre
cn -= 1

if cn == 0 && kg_curr != nil {
kg_tail.Next = kg_curr
kg_dummyNode = kg_tail
kg_pre = kg_curr
kg_curr = kg_pre.Next
kg_tail = kg_pre
cn = k - 1
}
}
kg_tail.Next = nil

if cn > 0 {
pre := kg_dummyNode.Next
curr := pre.Next
pre.Next = nil
for curr != nil {
pre = curr
curr = curr.Next

pre.Next = kg_dummyNode.Next
kg_dummyNode.Next = pre
}
}

return dummyNode.Next
}

3.2 DONE 双向链表

  • State "DONE" from "TODO" [2018-03-26 Mon 17:27]

3.2.1 DONE All O`one Data Structure

  • State "DONE" from "TODO" [2018-03-26 Mon 17:26]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
package main

import (
"container/list"
"fmt"
)

type Ele struct {
Key string
Counter int
}

type AllOne struct {
EleM map[string]*list.Element
Lst *list.List
}

/** Initialize your data structure here. */
func Constructor() AllOne {
return AllOne{
Lst: list.New(),
EleM: make(map[string]*list.Element),
}
}

/** Inserts a new key <Key> with value 1. Or increments an existing key by 1. */
func (this *AllOne) Inc(key string) {
if e, ok := this.EleM[key]; ok {
e.Value.(*Ele).Counter += 1
next := e
for {
if next == nil {
break
}
if next.Value.(*Ele).Counter > e.Value.(*Ele).Counter {
break
} else {
next = next.Next()
}
}

if next == nil {
this.Lst.MoveToBack(e)
} else {
this.Lst.MoveBefore(e, next)
}
} else {
ele := &Ele{
Key: key,
Counter: 1,
}
e := this.Lst.PushFront(ele)
this.EleM[key] = e
}
return
}

/** Decrements an existing key by 1. If Key's value is 1, remove it from the data structure. */
func (this *AllOne) Dec(key string) {
if e, ok := this.EleM[key]; ok {
ele := e.Value.(*Ele)
if ele.Counter == 1 {
this.Lst.Remove(e)
delete(this.EleM, key)
} else {
ele.Counter -= 1
prev := e
for {
if prev == nil {
break
}

if prev.Value.(*Ele).Counter < ele.Counter {
break
} else {
prev = prev.Prev()
}
}
if prev == nil {
this.Lst.MoveToFront(e)
} else {
fmt.Println("prev: ", prev.Value)
this.Lst.MoveAfter(e, prev)
}
}
}
return
}

/** Returns one of the keys with maximal value. */
func (this *AllOne) GetMaxKey() string {
tail := this.Lst.Back()
if tail != nil {
return tail.Value.(*Ele).Key
} else {
return ""
}
}

/** Returns one of the keys with Minimal value. */
func (this *AllOne) GetMinKey() string {
head := this.Lst.Front()
if head != nil {
return head.Value.(*Ele).Key
} else {
return ""
}
}

func (this *AllOne) Debug() {
fmt.Println(this.EleM)
for e := this.Lst.Front(); e != nil; e = e.Next() {
fmt.Println(e.Value)
}
}

func main() {
ao := Constructor()
ao.Inc("b")
ao.Inc("a")
ao.Debug()
ao.Inc("a")
ao.Debug()
ao.Inc("b")
ao.Debug()
ao.Inc("a")
ao.Debug()
ao.Inc("c")
ao.Dec("c")
ao.Dec("a")
ao.Dec("a")
ao.Debug()
fmt.Println(ao.GetMaxKey())
fmt.Println(ao.GetMinKey())
}

4 DONE LIFO 栈

  • State "DONE" from "TODO" [2018-03-27 Tue 22:45]

4.1 DONE 实现

  • State "DONE" from [2018-03-27 Tue 17:21]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
type Stack struct {
lst *list.List
}

func New() *Stack {
return &Stack{
lst: list.New(),
}
}

func (s *Stack) Len() int {
return s.lst.Len()
}

func (s *Stack) Empty() bool {
return s.lst.Len() == 0
}

func (s *Stack) Push(v interface{}) {
s.lst.PushBack(v)
}

func (s *Stack) Pop() interface{} {
back := s.lst.Back()
if back != nil {
return s.lst.Remove(back)
} else {
return nil
}
}

func (s *Stack) Top() interface{} {
back := s.lst.Back()
if back != nil {
return back.Value
} else {
return nil
}
}
1
2
3
4
5
6
7
8
9
10
11
12
func main() {
s := New()
s.Push(1)
s.Push(2)
s.Push(3)
fmt.Println(s.Top())
fmt.Println(s.Pop())
fmt.Println(s.Top())
fmt.Println(s.Pop())
fmt.Println(s.Top())
fmt.Println(s.Pop())
}

4.2 DONE 应用

  • State "DONE" from "TODO" [2018-03-27 Tue 22:45]

4.2.1 DONE Implement Queue using Stacks

  • State "DONE" from "TODO" [2018-03-27 Tue 22:44]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
type MyQueue struct {
ss *Stack
hs *Stack
}

/** Initialize your data structure here. */
func Constructor() MyQueue {
return MyQueue{
ss: New(),
hs: New(),
}
}

/** Push element x to the back of queue. */
func (this *MyQueue) Push(x int) {
for !this.ss.Empty() {
this.hs.Push(this.ss.Pop())
}
this.ss.Push(x)
for !this.hs.Empty() {
this.ss.Push(this.hs.Pop())
}
}

/** Removes the element from in front of queue and returns that element. */
func (this *MyQueue) Pop() int {
return this.ss.Pop().(int)
}

/** Get the front element. */
func (this *MyQueue) Peek() int {
return this.ss.Top().(int)
}

/** Returns whether the queue is empty. */
func (this *MyQueue) Empty() bool {
return this.ss.Empty()
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
package main



func main() {
q := Constructor()
q.Push(1)
q.Push(2)
q.Push(3)
fmt.Println(q.Peek())
fmt.Println(q.Pop())
fmt.Println(q.Peek())
fmt.Println(q.Pop())
q.Push(4)
fmt.Println(q.Peek())
fmt.Println(q.Pop())
fmt.Println(q.Peek())
fmt.Println(q.Pop())
}

5 DONE FIFO 队列

5.1 DONE 实现

  • State "DONE" from [2018-03-27 Tue 17:22]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
type Queue struct {
lst *list.List
}

func New() *Queue {
return &Queue{
lst: list.New(),
}
}

func (q *Queue) Len() int {
return q.lst.Len()
}

func (q *Queue) Empty() bool {
return q.lst.Len() == 0
}

func (q *Queue) Front() interface{} {
front := q.lst.Front()
if front != nil {
return front.Value
} else {
return nil
}
}

func (q *Queue) Peek() interface{} {
return q.Front()
}

func (q *Queue) Push(v interface{}) {
q.lst.PushBack(v)
}

func (q Queue) Back() interface{} {
back := q.lst.Back()
if back != nil {
return back.Value
} else {
return nil
}
}

func (q *Queue) Pop() interface{} {
front := q.lst.Front()
if front != nil {
return q.lst.Remove(front)
} else {
return nil
}
}

5.2 DONE 应用

  • State "DONE" from "TODO" [2018-03-27 Tue 22:44]

5.2.1 DONE Implement Stack using Queues

  • State "DONE" from "TODO" [2018-03-27 Tue 22:44]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
type MyStack struct {
q *Queue
hq *Queue
}

/** Initialize your data structure here. */
func Constructor() MyStack {
return MyStack{
q: New(),
hq: New(),
}
}

/** Push element x onto stack. */
func (this *MyStack) Push(x int) {
for !this.q.Empty() {
this.hq.Push(this.q.Pop())
}
this.q.Push(x)
for !this.hq.Empty() {
this.q.Push(this.hq.Pop())
}
}

/** Removes the element on top of the stack and returns that element. */
func (this *MyStack) Pop() int {
return this.q.Pop().(int)
}

/** Get the top element. */
func (this *MyStack) Top() int {
return this.q.Peek().(int)
}

/** Returns whether the stack is empty. */
func (this *MyStack) Empty() bool {
return this.q.Empty()
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
package main



func main() {
s := Constructor()
s.Push(1)
s.Push(2)
s.Push(3)
fmt.Println(s.Top())
fmt.Println(s.Pop())
fmt.Println(s.Top())
fmt.Println(s.Pop())
s.Push(4)
fmt.Println(s.Top())
fmt.Println(s.Pop())
fmt.Println(s.Top())
fmt.Println(s.Pop())
}

6 DONE 二叉堆

6.1 DONE 实现堆

  • State "DONE" from "TODO" [2018-03-23 Fri 18:10]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
type LessFunc func(int, int) bool

type Heap struct {
nums []int
size int
capacity int
lessFunc LessFunc
}

func parent(i int) int {
return (i - 1) / 2
}

func left(i int) int {
return 2*i + 1
}

func right(i int) int {
return 2*i + 2
}

func NewHeap(nums []int, lessFunc LessFunc) *Heap {
cnums := make([]int, len(nums))
copy(cnums, nums)
h := &Heap{
nums: cnums,
size: len(nums),
capacity: len(nums),
lessFunc: lessFunc,
}

for i := len(nums) / 2; i >= 0; i -= 1 {
h.down(i, len(nums)-1)
}

return h
}

func (h *Heap) down(start, end int) {
p := start
l := left(p)
for {
if l > end {
break
}

if l < end && h.lessFunc(h.nums[l], h.nums[l+1]) {
l += 1
}

if !h.lessFunc(h.nums[p], h.nums[l]) {
break
} else {
h.nums[l], h.nums[p] = h.nums[p], h.nums[l]
p = l
l = left(p)
}
}

return
}

func (h *Heap) up(start, end int) {
p := parent(end)
c := end
for {
if p < start {
break
}

if !h.lessFunc(h.nums[p], h.nums[c]) {
break
} else {
h.nums[c], h.nums[p] = h.nums[p], h.nums[c]
c = p
p = parent(p)
}
}

return
}

func (h *Heap) Push(num int) {
if h.size+1 > h.capacity {
h.capacity *= 2
cnums := make([]int, h.capacity)
copy(cnums, h.nums)
h.nums = cnums
}

h.nums[h.size] = num
h.size += 1
h.up(0, h.size-1)

return
}

func (h *Heap) Pop() (int, error) {
if h.size < 1 {
return 0, errors.New("empty")
}

h.size -= 1
h.nums[h.size], h.nums[0] = h.nums[0], h.nums[h.size]
h.down(0, h.size-1)
return h.nums[h.size], nil
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
package main

import (
"fmt"
"errors"
)



func main() {
nums := []int{2, 4, 6, 3, 5, 7, 1, 10, 8, 9}
h := NewHeap(nums, func(a, b int) bool {
if a < b {
return true
} else {
return false
}
})
h.Log()
dn, _ := h.Del()
fmt.Println(dn)
h.Log()
h.Insert(11)
h.Log()
}

6.2 DONE 堆的应用

  • State "DONE" from "TODO" [2018-03-26 Mon 14:07]

6.2.1 DONE Find Median from Data Stream

  • State "DONE" from "TODO" [2018-03-26 Mon 14:07]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
package main

import (
"container/heap"
"fmt"
)

type MyMaxHeap []int

func (h MyMaxHeap) Len() int { return len(h) }
func (h MyMaxHeap) Less(i, j int) bool { return h[i] > h[j] }
func (h MyMaxHeap) Swap(i, j int) { h[i], h[j] = h[j], h[i] }

func (h *MyMaxHeap) Push(e interface{}) {
*h = append(*h, e.(int))
}

func (h *MyMaxHeap) Pop() interface{} {
old := *h
n := len(old)
e := old[n-1]
*h = old[0 : n-1]
return e
}

type MyMinHeap []int

func (h MyMinHeap) Len() int { return len(h) }
func (h MyMinHeap) Less(i, j int) bool { return h[i] < h[j] }
func (h MyMinHeap) Swap(i, j int) { h[i], h[j] = h[j], h[i] }

func (h *MyMinHeap) Push(e interface{}) {
*h = append(*h, e.(int))
}

func (h *MyMinHeap) Pop() interface{} {
old := *h
n := len(old)
e := old[n-1]
*h = old[0 : n-1]
return e
}

type MedianFinder struct {
LH *MyMaxHeap
RH *MyMinHeap
Lsize int
Rsize int
}

/** initialize your data structure here. */
func Constructor() MedianFinder {
return MedianFinder{
LH: &MyMaxHeap{},
RH: &MyMinHeap{},
}
}

func (this *MedianFinder) AddNum(num int) {
if this.Lsize == 0 {
heap.Push(this.LH, num)
this.Lsize += 1
return
}
lnum := heap.Pop(this.LH).(int)

if this.Rsize == 0 {
if num < lnum {
lnum, num = num, lnum
}

heap.Push(this.LH, lnum)
heap.Push(this.RH, num)
this.Rsize += 1
return
}

rnum := heap.Pop(this.RH).(int)
if num < lnum {
lnum, num = num, lnum
}
if rnum < num {
num, rnum = rnum, num
}

if this.Lsize < this.Rsize {
heap.Push(this.LH, lnum)
heap.Push(this.LH, num)
heap.Push(this.RH, rnum)
this.Lsize += 1
} else {
heap.Push(this.LH, lnum)
heap.Push(this.RH, num)
heap.Push(this.RH, rnum)
this.Rsize += 1
}

return
}

func (this *MedianFinder) FindMedian() float64 {
if this.Lsize == this.Rsize {
if this.Lsize == 0 {
return 0.0
} else {
return (float64((*(this.LH))[0]) + float64((*(this.RH))[0]))/2.0
}
}

if this.Lsize > this.Rsize {
return float64((*this.LH)[0])
} else {
return float64((*this.RH)[0])
}
}

func main() {
mf := Constructor()
mf.AddNum(1)
fmt.Println(mf.FindMedian())
mf.AddNum(2)
fmt.Println(mf.FindMedian())
mf.AddNum(3)
fmt.Println(mf.FindMedian())
mf.AddNum(4)
fmt.Println(mf.FindMedian())
}

7 DONE 二项堆

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
type BinHeapNode struct {
Parent *BinHeapNode
Child *BinHeapNode
Sibling *BinHeapNode
Key int
Degree int
}

type BinHeap struct {
Head *BinHeapNode
}

func MakeBinHeap() *BinHeap {
return &BinHeap{}
}

func BinHeapMinimum(h *BinHeap) *BinHeapNode {
var y *BinHeapNode
x := h.Head
min := math.MaxInt32
for x != nil {
if x.Key < min {
min = x.Key
y = x
}
x = x.Sibling
}

return y
}

func BinLink(y, z *BinHeapNode) {
y.Parent = z
y.Sibling = z.Child
z.Child = y
z.Degree += 1
}

func BinHeapMerge(lh, rh *BinHeap) *BinHeap {
dummyNode := &BinHeapNode{}
dummy := dummyNode
ln, rn := lh.Head, rh.Head
for ln != nil && rn != nil {
if ln.Degree < rn.Degree {
dummy.Sibling = ln
ln = ln.Sibling
} else {
dummy.Sibling = rn
rn = rn.Sibling
}
dummy = dummy.Sibling
}

if ln != nil {
dummy.Sibling = ln
}

if rn != nil {
dummy.Sibling = rn
}

h := MakeBinHeap()
h.Head = dummyNode.Sibling
return h
}

func BinHeapUnion(lh, rh *BinHeap) *BinHeap {
h := BinHeapMerge(lh, rh)
lh.Head, rh.Head = nil, nil
if h == nil {
return h
}

var prev_x *BinHeapNode
x := h.Head
next_x := x.Sibling
for next_x != nil {
if x.Degree != next_x.Degree ||
(next_x.Sibling != nil && next_x.Sibling.Degree == x.Degree) {
prev_x = x
x = next_x
} else if x.Key <= next_x.Key {
x.Sibling = next_x.Sibling
BinLink(next_x, x)
} else {
if prev_x == nil {
h.Head = next_x
} else {
prev_x.Sibling = next_x
}
BinLink(x, next_x)
x = next_x
}

next_x = x.Sibling
}
return h
}

func BinHeapInsert(h *BinHeap, x *BinHeapNode) *BinHeap {
nh := MakeBinHeap()
x.Parent, x.Child, x.Sibling = nil, nil, nil
x.Degree = 0
nh.Head = x
h = BinHeapUnion(h, nh)
return h
}

func BinHeapExtractMin(h *BinHeap) (*BinHeap, *BinHeapNode) {
var y, prev_y, prev_x *BinHeapNode
x := h.Head
min := math.MaxInt32
for x != nil {
if x.Key < min {
min = x.Key
y = x
prev_y = prev_x
}
prev_x = x
x = x.Sibling
}

if prev_y != nil {
prev_y.Sibling = y.Sibling
} else {
h.Head = y.Sibling
}

nh := MakeBinHeap()
x = y.Child
for x != nil {
z := x.Sibling
x.Sibling = nh.Head
nh.Head = x
x = z
}
h = BinHeapUnion(h, nh)

return h, y
}

func BinHeapDecrKey(h *BinHeap, x *BinHeapNode, k int) {
if k > x.Key {
panic("new key is greater than current key")
}

x.Key = k
y := x
z := y.Parent
for z != nil && y.Key < z.Key {
y.Key, z.Key = z.Key, y.Key
y = z
z = y.Parent
}
}

func BinHeapDelete(h *BinHeap, x *BinHeapNode) {
BinHeapDecrKey(h, x, math.MinInt32)
BinHeapExtractMin(h)
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
package main

import (
"math"
"fmt"
)



func main() {
lh := MakeBinHeap()
x := &BinHeapNode{
Key: 1,
}
y := &BinHeapNode{
Key: 2,
}
z := &BinHeapNode{
Key: 3,
}
w := &BinHeapNode{
Key: 4,
}
lh = BinHeapInsert(lh, x)
lh = BinHeapInsert(lh, y)
lh = BinHeapInsert(lh, z)
lh = BinHeapInsert(lh, w)
lh,_ =BinHeapExtractMin(lh)
fmt.Println(BinHeapMinimum(lh))
}

8 DONE 斐波那契堆

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
type FibHeapNode struct {
Parent *FibHeapNode
Child *FibHeapNode
Left *FibHeapNode
Right *FibHeapNode
Key int
Degree int
Mark bool
}

type FibHeap struct {
Min *FibHeapNode
Size int
}

func MakeFibHeap() *FibHeap {
return &FibHeap{}
}

func fibHeapNodeRemove(x *FibHeapNode) {
x.Left.Right = x.Right
x.Right.Left = x.Left
}

func fibHeapNodeAdd(T, x *FibHeapNode) {
T.Left.Right = x
x.Left = T.Left
x.Right = T
T.Left = x
}

func fibHeapNodeUnion(lhn, rhn *FibHeapNode) {
lhn.Left.Right = rhn.Left
rhn.Left.Left = lhn.Left
lhn.Left = rhn
rhn.Right = lhn
}

func FibHeapInsert(h *FibHeap, x *FibHeapNode) {
x.Degree = 0
x.Mark = false
x.Parent, x.Child = nil, nil
x.Left, x.Right = x, x

if h.Min == nil {
h.Min = x
} else {
fibHeapNodeAdd(h.Min, x)
}

if h.Min.Key > x.Key {
h.Min = x
}

h.Size += 1
return
}

func FibHeapMinimum(h *FibHeap) *FibHeapNode {
return h.Min
}

func FibHeapUnion(lh, rh *FibHeap) *FibHeap {
h := MakeFibHeap()
h.Min = lh.Min
if h.Min != nil && rh.Min != nil {
fibHeapNodeUnion(h.Min, rh.Min)
} else if h.Min == nil {
h.Min = rh.Min
}

if h.Min != nil && rh.Min != nil && h.Min.Key > rh.Min.Key {
h.Min = rh.Min
}

h.Size = lh.Size + rh.Size
lh.Min, rh.Min = nil, nil
lh.Size, rh.Size = 0, 0

return h
}

func FibHeapMinRemove(h *FibHeap) *FibHeapNode {
min := h.Min
if min == min.Right {
h.Min = nil
} else {
h.Min = min.Right
fibHeapNodeRemove(min)
}

min.Left, min.Right = min, min
return min
}

func FibHeapExtractMin(h *FibHeap) *FibHeapNode {
z := h.Min
if z == nil {
return z
}

x := z.Child
if x != nil {
y := x
for y.Right != x {
y.Parent = nil
y = y.Right
}
y.Parent = nil

fibHeapNodeUnion(h.Min, x)
}
fibHeapNodeRemove(z)
z.Child = nil

if z == z.Right {
h.Min = nil
} else {
h.Min = z.Right
consolidate(h)
}
h.Size -= 1

z.Left, z.Right = z, z
return z
}

func FibHeapLink(h *FibHeap, y, x *FibHeapNode) {
fibHeapNodeRemove(y)

z := x.Child
if z != nil {
fibHeapNodeAdd(z, y)
} else {
x.Child = y
y.Parent = x
}

x.Degree += 1
y.Mark = false
return
}

func consolidate(h *FibHeap) {
d := int(math.Floor(math.Log2(float64(h.Size))) + 1.0)
dArr := make([]*FibHeapNode, d)

for nil != h.Min {
x := FibHeapMinRemove(h)
degree := x.Degree
for dArr[degree] != nil {
y := dArr[degree]
if x.Key > y.Key {
x, y = y, x
}
FibHeapLink(h, y, x)
dArr[degree] = nil
degree += 1
}
dArr[degree] = x
}

h.Min = nil
for i, _ := range dArr {
if dArr[i] != nil {
x := dArr[i]
if h.Min != nil {
fibHeapNodeAdd(h.Min, x)
} else {
h.Min = x
x.Right = x
x.Left = x
}

if h.Min.Key > x.Key {
h.Min = x
}
}
}

return
}

func FibHeapDecrKey(h *FibHeap, x *FibHeapNode, key int) {
if key > x.Key {
panic("new key is greater than current key.")
}

x.Key = key
y := x.Parent
if y != nil && x.Key < y.Key {
cut(h, x, y)
cascadingCut(h, y)
}

if x.Key < h.Min.Key {
h.Min = x
}
return
}

func cut(h *FibHeap, x, y *FibHeapNode) {
fibHeapNodeRemove(x)
renewDegree(y, x.Degree)
if x == x.Right {
y.Child = nil
} else {
y.Child = x.Right
}

x.Left, x.Right = x, x
x.Parent = nil
x.Mark = false
fibHeapNodeAdd(h.Min, x)
return
}

func cascadingCut(h *FibHeap, y *FibHeapNode) {
z := y.Parent
if z != nil {
if y.Mark == false {
y.Mark = true
} else {
cut(h, y, z)
cascadingCut(h, z)
}
}
return
}

func renewDegree(y *FibHeapNode, degree int) {
y.Degree -= degree
if y.Parent != nil {
renewDegree(y.Parent, degree)
}
}

func FibHeapDelete(h *FibHeap, x *FibHeapNode) {
FibHeapDecrKey(h, x, math.MinInt32)
FibHeapExtractMin(h)
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
package main

import "fmt"
import "math"



func main() {
lh := MakeFibHeap()
x := &FibHeapNode{
Key: 1,
}
y := &FibHeapNode{
Key: 2,
}
z := &FibHeapNode{
Key: 3,
}
w := &FibHeapNode{
Key: 4,
}

FibHeapInsert(lh, x)
FibHeapInsert(lh, y)
FibHeapInsert(lh, z)
FibHeapInsert(lh, w)
fmt.Println(FibHeapMinimum(lh))
fmt.Println(FibHeapExtractMin(lh))
fmt.Println(lh, *y, *z, *w)
FibHeapDecrKey(lh, w, -3)
fmt.Println(FibHeapExtractMin(lh))
fmt.Println(FibHeapMinimum(lh))
}

9 WAITING 二叉查找树

  • State "WAITING" from "TODO" [2018-04-25 Wed 10:29]
    等待被测试
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
type TreeNode struct {
Parent *TreeNode
Left *TreeNode
Right *TreeNode
Key int
}

type Tree struct {
Root *TreeNode
}

func TreeSearch(x *TreeNode, k int) *TreeNode {
if x == nil || k == x.Key {
return x
}

if k < x.Key {
return TreeSearch(x.Left, k)
} else {
return TreeSearch(x.Right, k)
}
}

func IterativeTreeSearch(x *TreeNode, k int) *TreeNode {
for x != nil && k != x.Key {
if k < x.Key {
x = x.Left
} else {
x = x.Right
}
}

return x
}

func TreeMinimum(x *TreeNode) *TreeNode {
for x.Left != nil {
x = x.Left
}
return x
}

func TreeMaximum(x *TreeNode) *TreeNode {
for x.Right != nil {
x = x.Right
}

return x
}

func TreeSuccessor(x *TreeNode) *TreeNode {
if x.Right != nil {
return TreeMinimum(x.Right)
}

y := x.Parent
for y != nil && x == y.Right {
x = y
y = y.Parent
}

return y
}

func TreePredecessor(x *TreeNode) *TreeNode {
if x.Left != nil {
return TreeMaximum(x.Left)
}

y := x.Parent
for y != nil && x == y.Left {
x = y
y = y.Parent
}

return y
}

func TreeInsert(T *Tree, z *TreeNode) {
var y *TreeNode
x := T.Root

for x != nil {
y = x
if z.Key < x.Key {
x = x.Left
} else {
x = x.Right
}
}

z.Parent = y
if y == nil {
T.Root = z
} else {
if z.Key < y.Key {
y.Left = z
} else {
y.Right = z
}
}

return
}

func TreeDelete(T *Tree, z *TreeNode) {
var x, y *TreeNode
if z.Left == nil || z.Right == nil {
y = z
} else {
y = TreeSuccessor(z)
}

if y.Left != nil {
x = y.Left
} else {
x = y.Right
}

if x != nil {
x.Parent = y.Parent
}

if y.Parent == nil {
T.Root = x
} else {
if y == y.Parent.Left {
y.Parent.Left = x
} else {
y.Parent.Right = x
}
}

if y != z {
z.Key = y.Key
}

return
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
package main

import (
"fmt"
"math/rand"
)



func main() {
t := &Tree{}
numM := make(map[int]bool)
cn := 0
for cn < 50 {
num := rand.Intn(1000)
if !numM[num] {
cn += 1
numM[num] = true
tn := &TreeNode{
Key: num,
}
TreeInsert(t, tn)
}
}
fmt.Println(TreeMinimum(t.Root))
fmt.Println(TreeMaximum(t.Root))
}

10 TODO 红黑树

#+NAME left-leaning-red-black-tree

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
const (
RED = true
BLACK = false
)

const (
BST = iota
TD234
BU23
)

type Node struct {
Left *Node
Right *Node
Color bool
Key int
Val interface{}
}

func isRed(x *Node) bool {
if x == nil {
return false
}

return x.Color == RED
}

type LLRBTree struct {
Root *Node
}

func (t *LLRBTree) Get(key int) interface{} {
x := t.Root
for x != nil {
if key < x.Key {
x = x.Left
} else if key > x.Key {
x = x.Right
} else {
return x.Val
}
}

return nil
}

// Make a right-leaning 3-node lean to the left.
func rotateLeft(h *Node) *Node {
x := h.Right
h.Right = x.Left
x.Left = h
x.Color = x.Left.Color
x.Left.Color = RED
return x
}

// Make a left-leaning 3-node lean to the right.
func rotateRight(h *Node) *Node {
x := h.Left
h.Left = x.Right
x.Right = h
x.Color = x.Right.Color
x.Right.Color = RED
return x
}

func colorFlip(x *Node) {
x.Color = !x.Color
x.Left.Color = !x.Left.Color
x.Right.Color = !x.Right.Color
}

func insert(h *Node, key int, val interface{}) {
// insert at the bottom
if h == nil {
return &Node{Key: key, Val: val}
}

// split 4-nodes on the way down
if isRed(h.left) && isRed(h.right) {
colorFlip(h)
}

// standard BST insert code
if key < h.Key {
h.Left = insert(h.Left, key, val)
} else if key > h.Key {
h.Right = insert(h.Right, key, val)
} else {
h.Val = val
}

// fix right-leaning reds on the way up
if isRed(h.Right) {
h = rotateLeft(h)
}

// fix two reds in a row on the way up
if isRed(h.Left) && isRed(h.Left.Left) {
h = rotateRight(h)
}

return h
}

func (t *LLRBTree) Put(key int, val interface{}) {
t.Root = insert(t.Root, key, val)
root.Color = BLACK
return
}

func fixUp(h *Node) *Node {
// fix right-leaning reds on the way up
if isRed(h.Right) {
h = rotateLeft(h)
}

// fix two reds in a row on the way up
if isRed(h.Left) && isRed(h.Left.Left) {
h = rotateRight(h)
}

// split 4-nodes on the way down
if isRed(h.Left) && isRed(h.Right) {
colorFlip(h)
}

return h
}

// Assuming that h is red and both h.right and h.right.left
// are black, make h.right or one of its children red.
func moveRedRight(h *Node) *Node {
colorFlip(h)
if isRed(h.Left.Left) {
h = rotateRight(h)
colorFlip(h)
}
return h
}

func deleteMax(h *Node) *Node {
// lean 3-nodes to the right
if isRed(h.Left) {
h = rotateRight(h)
}

// remove node on bottom level
if h.Right == nil {
return nil
}

// push red link down if necessary
if !isRed(h.Right) && !isRed(h.Right.Left) {
h = moveRedRight(h)
}

// move down one level
h.Right = deleteMax(h.Right)

// fix right-leaning red links and eliminate 4-nodes on the way up
return fixUp(h)
}

func (t *LLRBTree) deleteMax() {
t.Root = deleteMax(t.Root)
t.Root.Color = BLACK
}

// Assuming that h is red and both h.left and h.left.left
// are black, make h.left or one of its children red.
func moveRedLeft(h *Node) *Node {
colorFlip(h)
if isRed(h.Right.Left) {
h.Right = rotateRight(h.Right)
h = rotateLeft(h)
colorFlip(h)
}

return h
}

func deleteMin(h *Node) *Node {
// remove node on bottom level
if h.Left == nil {
return nil
}

// push red link down if necessary
if !isRed(h.Left) && !isRed(h.Left.Left) {
h = moveRedLeft(h)
}

// move down one level
h.Left = deleteMin(h.Left)

// fix right-leaning red links and eliminate 4-nodes on the way up
return fixUp(h)
}

func (t *LLRBTree) deleteMin() {
t.Root = deleteMin(t.Root)
t.Root.Color = BLACK
}

func (t *LLRBTree) min() *Node {
x := t.Root
y := x
for x != nil {
y = x
x = x.Left
}

return y
}

func del(h *Node, key int) *Node {
if key < h.Key { // LEFT
// push red link down if necessary
if !isRed(h.Left) && !isRed(h.Left.Left) {
h = moveRedLeft(h)
}

// move down(left)
h.Left = del(h.Left, key)
} else { // RIGHT or EQUAL
// lean 3-nodes to the right
if isRed(h.Left) {
h = rotateRight(h)
}

// EQUAL(at bottom) delete node
if cmp == 0 && h.Right == nil {
return nil
}

// push red right if necessary
if !isRed(h.Right) && !isRed(h.Right.Left) {
h = moveRedRight(h)
}

if key == h.Key {
successor := t.min(h.Right)
h.Key = successor.Key
h.Val = successor.Val
h.right = deleteMin(h.Right)
} else {
// move down(right)
h.Right = del(h.Right, key)
}
}

return fixUp(h)
}

func (t *LLRBTree) Delete(key int) {
t.Root = del(t.Root, key)
t.Root.Color = BLACK
return
}

11 TODO B树

12 DONE 图

  • State "DONE" from "TODO" [2018-04-15 Sun 16:49]

12.1 DONE 定义

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
type ArcNode struct {
AdjVex int
Info interface{}
}

type VNode struct {
Data interface{}
ArcNodeArr []ArcNode
}

type AdjList []VNode

func MakeDot(vertices AdjList) string {
var ans string
for u, _ := range vertices {
for i := 0; i < len(vertices[u].ArcNodeArr); i += 1 {
v := vertices[u].ArcNodeArr[i].AdjVex
ans += fmt.Sprintf("%v -> %v;\n", u, v)
}
}
return ans
}

func makeDotScb(scb [][]int, vertices AdjList) string {
var clusters string
for i, _ := range scb {
arr := scb[i]
var node_str string
for _, u := range arr {
node_str += fmt.Sprintf("%v; ", u)
}
cluster_str := fmt.Sprintf("subgraph \"cluster-%v\" {\n\t label=\"scb-%v\";\n\t %v \n}\n", i, i, node_str)
clusters += cluster_str
}
return MakeDot(vertices) + clusters
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
package main

import "fmt"



func main() {
vertices := AdjList{
VNode{
Data: 0,
ArcNodeArr: []ArcNode{
ArcNode{AdjVex: 1},
ArcNode{AdjVex: 2},
},
},
VNode{
Data: 1,
ArcNodeArr: []ArcNode{
ArcNode{AdjVex: 2},
ArcNode{AdjVex: 3},
},
},
VNode{
Data: 2,
ArcNodeArr: []ArcNode{
ArcNode{AdjVex: 1},
},
},
VNode{
Data: 3,
ArcNodeArr: []ArcNode{},
},
VNode{
Data: 4,
ArcNodeArr: []ArcNode{
ArcNode{AdjVex: 2},
ArcNode{AdjVex: 3},
},
},
}

fmt.Println("{rank=same; 2 3;}\n"+ MakeDot(vertices))
}
digraph {
 $input
}
1
2
3
4
5
6
7
type Edge struct {
Start int
End int
Weight int
}

type EdgeList []Edge

12.2 DONE 广度优先搜索(BFS)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
func bfs(vertices AdjList, u int, visitFunc func(interface{})) {
q := New()
visited := make([]int, len(vertices))

visitFunc(vertices[u].Data)
q.Push(u)
visited[u] = 1

for !q.Empty() {
v := q.Pop().(int)

for j := 0; j < len(vertices[v].ArcNodeArr); j += 1 {
if visited[vertices[v].ArcNodeArr[j].AdjVex] != 1 {
visitFunc(vertices[v].ArcNodeArr[j].AdjVex)
q.Push(vertices[v].ArcNodeArr[j].AdjVex)
visited[vertices[v].ArcNodeArr[j].AdjVex] = 1
}
}
}

return
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
package main

import "fmt"
import "container/list"





func main() {
vertices := AdjList{
VNode{
Data: 1,
ArcNodeArr: []ArcNode{
ArcNode{AdjVex: 1},
ArcNode{AdjVex: 2},
},
},
VNode{
Data: 2,
ArcNodeArr: []ArcNode{
ArcNode{AdjVex: 2},
ArcNode{AdjVex: 3},
},
},
VNode{
Data: 3,
ArcNodeArr: []ArcNode{
ArcNode{AdjVex: 1},
ArcNode{AdjVex: 2},
},
},
VNode{
Data: 4,
ArcNodeArr: []ArcNode{
ArcNode{AdjVex: 0},
},
},
VNode{
Data: 5,
ArcNodeArr: []ArcNode{
ArcNode{AdjVex: 2},
ArcNode{AdjVex: 3},
},
},
}

bfs(vertices, 0, func(data interface{}) {
fmt.Println(data)
})
}

12.3 DONE 深度优先搜索(DFS)

  • State "DONE" from "TODO" [2018-04-09 Mon 11:52]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
func dfs(vertices AdjList, visitFunc func(interface{})) {
visited := make([]int, len(vertices))

for u := 0; u < len(vertices); u += 1 {
if visited[u] != 1 {
dfsVisit(vertices, u, visited, visitFunc)
}
}
return
}

func dfsVisit(vertices AdjList, u int, visited []int, visitFunc func(interface{})) {
visited[u] = 1
visitFunc(vertices[u].Data)
for i := 0; i < len(vertices[u].ArcNodeArr); i += 1 {
v := vertices[u].ArcNodeArr[i].AdjVex
if visited[v] != 1 {
dfsVisit(vertices, v, visited, visitFunc)
}
}
return
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
package main

import "fmt"




func main() {
vertices := AdjList{
VNode{
Data: 1,
ArcNodeArr: []ArcNode{
ArcNode{AdjVex: 1},
ArcNode{AdjVex: 2},
},
},
VNode{
Data: 2,
ArcNodeArr: []ArcNode{
ArcNode{AdjVex: 2},
ArcNode{AdjVex: 3},
},
},
VNode{
Data: 3,
ArcNodeArr: []ArcNode{
ArcNode{AdjVex: 1},
ArcNode{AdjVex: 2},
},
},
VNode{
Data: 4,
ArcNodeArr: []ArcNode{
ArcNode{AdjVex: 0},
},
},
VNode{
Data: 5,
ArcNodeArr: []ArcNode{
ArcNode{AdjVex: 2},
ArcNode{AdjVex: 3},
},
},
}

dfs(vertices, func(data interface{}) {
fmt.Println(data)
})
}

12.4 DONE Union-Find算法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
func hasCycle(edges EdgeList, vexNum int) bool {
var findFunc func([]int, int) int
findFunc = func(parent []int, i int) int {
if parent[i] == -1 {
return i
}
return findFunc(parent, parent[i])
}

unionFunc := func(parent []int, i, j int) {
iSet := findFunc(parent, i)
jSet := findFunc(parent, j)
parent[iSet] = jSet
}

parent := make([]int, vexNum)
for i, _ := range parent {
parent[i] = -1
}

for _, edge := range edges {
i := findFunc(parent, edge.Start)
j := findFunc(parent, edge.End)

if i == j {
return true
}

unionFunc(parent, i, j)
}

return false
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
package main

import "fmt"





func main() {
edges := []Edge{
Edge{Start: 0, End: 1},
Edge{Start: 1, End: 2},
Edge{Start: 2, End: 3},
}

fmt.Println(hasCycle(edges, 4))
}

12.5 DONE 拓扑排序

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
func TopologicalSort(vertices AdjList) ([]int, bool) {
q := New()
visited := make([]int, len(vertices))
indegree := make([]int, len(vertices))

for u := 0; u < len(vertices); u += 1 {
if visited[u] != 1 {
q.Push(u)
visited[u] = 1
for !q.Empty() {
v := q.Pop().(int)
for j := 0; j < len(vertices[v].ArcNodeArr); j += 1 {
indegree[vertices[v].ArcNodeArr[j].AdjVex] += 1
if visited[vertices[v].ArcNodeArr[j].AdjVex] != 1 {
q.Push(vertices[v].ArcNodeArr[j].AdjVex)
visited[vertices[v].ArcNodeArr[j].AdjVex] = 1
}
}
}
}
}

ans := make([]int, 0)
q = New()
for u := 0; u < len(vertices); u += 1 {
if indegree[u] == 0 {
q.Push(u)
}
}

for !q.Empty() {
u := q.Pop().(int)
ans = append(ans, u)

for j := 0; j < len(vertices[u].ArcNodeArr); j += 1 {
v := vertices[u].ArcNodeArr[j].AdjVex
indegree[v] -= 1
if indegree[v] == 0 {
q.Push(v)
}
}
}

return ans, len(vertices) == len(ans)
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
package main

import "fmt"
import "container/list"





func main() {
vertices := AdjList{
VNode{
Data: 0,
ArcNodeArr: []ArcNode{
ArcNode{AdjVex: 4},
},
},
VNode{
Data: 1,
ArcNodeArr: []ArcNode{
ArcNode{AdjVex: 0},
},
},
VNode{
Data: 2,
ArcNodeArr: []ArcNode{
ArcNode{AdjVex: 0},
ArcNode{AdjVex: 3},
},
},
VNode{
Data: 3,
ArcNodeArr: []ArcNode{
ArcNode{AdjVex: 1},
},
},
VNode{
Data: 4,
ArcNodeArr: []ArcNode{
ArcNode{AdjVex: 0},
ArcNode{AdjVex: 1},
},
},
VNode{
Data: 5,
ArcNodeArr: []ArcNode{
ArcNode{AdjVex: 0},
ArcNode{AdjVex: 2},
},
},
}

fmt.Println(TopologicalSort(vertices))
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
func TopologicalSort(vertices AdjList) ([]int, bool) {
s := New()
visited := make([]int, len(vertices))
father := make([]int, len(vertices))
for i, _ := range father {
father[i] = -1
}

var dfsVisit func(int)
dfsVisit = func(u int) {
visited[u] = 1
for i := 0; i < len(vertices[u].ArcNodeArr); i += 1 {
v := vertices[u].ArcNodeArr[i].AdjVex
if visited[v] == 1 {
tmp := u
for tmp != v && tmp > 0 {
fmt.Print(tmp, "->")
tmp = father[tmp]
}
fmt.Println(tmp)
} else if visited[v] != 2 {
father[v] = u
dfsVisit(v)
}
}
visited[u] = 2
s.Push(u)
return
}

for u := 0; u < len(vertices); u += 1 {
if visited[u] != 1 {
dfsVisit(u)
}
}

ans := make([]int, 0)
for !s.Empty() {
ans = append(ans, s.Pop().(int))
}

return ans, true
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
     package main

import "fmt"
import "container/list"





func main() {
vertices := AdjList{
VNode{
Data: 0,
ArcNodeArr: []ArcNode{
ArcNode{AdjVex: 4},
},
},
VNode{
Data: 1,
ArcNodeArr: []ArcNode{
ArcNode{AdjVex: 0},
},
},
VNode{
Data: 2,
ArcNodeArr: []ArcNode{
ArcNode{AdjVex: 0},
ArcNode{AdjVex: 3},
},
},
VNode{
Data: 3,
ArcNodeArr: []ArcNode{
ArcNode{AdjVex: 1},
},
},
VNode{
Data: 4,
ArcNodeArr: []ArcNode{
ArcNode{AdjVex: 0},
ArcNode{AdjVex: 1},
},
},
VNode{
Data: 5,
ArcNodeArr: []ArcNode{
ArcNode{AdjVex: 0},
ArcNode{AdjVex: 2},
},
},
}

fmt.Println(TopologicalSort(vertices))
}

12.6 DONE 强连通分支

  • State "DONE" from "TODO" [2018-04-15 Sun 16:49]

12.6.1 DONE Kosaraju算法

  • State "DONE" from "TODO" [2018-04-15 Sun 11:26]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
func reverse(vertices AdjList) AdjList {
rv := make(AdjList, len(vertices))
for u := 0; u < len(rv); u += 1 {
rv[u].Data = u
rv[u].ArcNodeArr = make([]ArcNode, 0)
}

for u := 0; u < len(vertices); u += 1 {
for j := 0; j < len(vertices[u].ArcNodeArr); j += 1 {
v := vertices[u].ArcNodeArr[j].AdjVex
rv[v].ArcNodeArr = append(
rv[v].ArcNodeArr,
ArcNode{
AdjVex: u,
})
}
}

return rv
}

func kosaraju(vertices AdjList) [][]int {
visited := make([]int, len(vertices))
dsfArr := make([]int, 0)
finArr := make([]int, 0)
var dfs func(AdjList, int)
dfs = func(vertices AdjList, u int) {
visited[u] = 1
dsfArr = append(dsfArr, u)
for i := 0; i < len(vertices[u].ArcNodeArr); i += 1 {
v := vertices[u].ArcNodeArr[i].AdjVex
if visited[v] != 1 {
dfs(vertices, v)
}
}
finArr = append(finArr, u)
}

for u := 0; u < len(vertices); u += 1 {
if visited[u] != 1 {
dfs(vertices, u)
}
}

rv := reverse(vertices)
visited = make([]int, len(vertices))
c_finArr := finArr
ans := make([][]int, 0)
for i := len(c_finArr) - 1; i >= 0; i -= 1 {
u := c_finArr[i]
if visited[u] != 1 {
dsfArr = make([]int, 0)
dfs(rv, u)
ans = append(ans, dsfArr)
}
}

return ans
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
package main

import "fmt"




func main() {
vertices := AdjList{
VNode{
Data: 0,
ArcNodeArr: []ArcNode{
ArcNode{AdjVex: 1},
ArcNode{AdjVex: 2},
},
},
VNode{
Data: 1,
ArcNodeArr: []ArcNode{
ArcNode{AdjVex: 3},
},
},
VNode{
Data: 2,
ArcNodeArr: []ArcNode{
ArcNode{AdjVex: 3},
ArcNode{AdjVex: 4},
},
},
VNode{
Data: 3,
ArcNodeArr: []ArcNode{
ArcNode{AdjVex: 0},
ArcNode{AdjVex: 5},
},
},
VNode{
Data: 4,
ArcNodeArr: []ArcNode{
ArcNode{AdjVex: 5},
},
},
VNode{
Data: 5,
ArcNodeArr: []ArcNode{
ArcNode{AdjVex: 4},
},
},
}

fmt.Println(makeDotScb(kosaraju(vertices), vertices))
}
digraph G {
$input
}

12.6.2 DONE Tarjan算法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
func tarjan(vertices AdjList) [][]int {
dsfArr := make([]int, len(vertices))
lowArr := make([]int, len(vertices))
inStack := make([]bool, len(vertices))
for i, _ := range dsfArr {
dsfArr[i] = -1
}

index := 0
s := New()
ans := make([][]int, 0)

var strongconnect func(int)
strongconnect = func(u int) {
dsfArr[u] = index
lowArr[u] = index
index += 1
inStack[u] = true
s.Push(u)

for i := 0; i < len(vertices[u].ArcNodeArr); i += 1 {
v := vertices[u].ArcNodeArr[i].AdjVex
if dsfArr[v] == -1 {
strongconnect(v)
if lowArr[v] < lowArr[u] {
lowArr[u] = lowArr[v]
}
} else if inStack[v] && lowArr[v] < lowArr[u] {
lowArr[u] = lowArr[v]
}
}

if dsfArr[u] == lowArr[u] {
arr := make([]int, 0)
v := s.Pop().(int)
for u != v {
inStack[v] = false
arr = append(arr, v)
v = s.Pop().(int)
}
inStack[v] = false
arr = append(arr, v)
ans = append(ans, arr)
}
}

for u := 0; u < len(vertices); u += 1 {
if dsfArr[u] == -1 {
strongconnect(u)
}
}

return ans
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
 package main

import "fmt"
import "container/list"







func main() {
vertices := AdjList{
VNode{
Data: 0,
ArcNodeArr: []ArcNode{
ArcNode{AdjVex: 1},
ArcNode{AdjVex: 2},
},
},
VNode{
Data: 1,
ArcNodeArr: []ArcNode{
ArcNode{AdjVex: 3},
},
},
VNode{
Data: 2,
ArcNodeArr: []ArcNode{
ArcNode{AdjVex: 3},
ArcNode{AdjVex: 4},
},
},
VNode{
Data: 3,
ArcNodeArr: []ArcNode{
ArcNode{AdjVex: 0},
ArcNode{AdjVex: 5},
},
},
VNode{
Data: 4,
ArcNodeArr: []ArcNode{
ArcNode{AdjVex: 5},
},
},
VNode{
Data: 5,
ArcNodeArr: []ArcNode{},
},
}

fmt.Println(makeDotScb(tarjan(vertices), vertices))
}
digraph G {
$input
}

12.6.3 DONE Gabow算法

  • State "DONE" from "TODO" [2018-04-15 Sun 16:49]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
func gabow(vertices AdjList) [][]int {
dsfArr := make([]int, len(vertices))
partArr := make([]int, len(vertices))
for i, _ := range dsfArr {
dsfArr[i] = -1
partArr[i] = -1
}
partIndex := 0
index := 0
ps := New()
rs := New()

var strongconnect func(int)
strongconnect = func(u int) {
dsfArr[u] = index
index += 1
ps.Push(u)
rs.Push(u)

for i := 0; i < len(vertices[u].ArcNodeArr); i += 1 {
v := vertices[u].ArcNodeArr[i].AdjVex
if dsfArr[v] == -1 {
strongconnect(v)
} else if partArr[v] == -1 {
for dsfArr[rs.Top().(int)] > dsfArr[v] {
rs.Pop()
}
}
}

if u == rs.Top().(int) {
rs.Pop()
partIndex += 1
v := ps.Pop().(int)
for u != v {
partArr[v] = partIndex
v = ps.Pop().(int)
}
partArr[v] = partIndex
}
}

for u := 0; u < len(vertices); u += 1 {
if dsfArr[u] == -1 {
strongconnect(u)
}
}

ans := make([][]int, 0)
for i := 1; i < partIndex+1; i += 1 {
arr := make([]int, 0)
for j := 0; j < len(partArr); j += 1 {
if partArr[j] == i {
arr = append(arr, j)
}
}
ans = append(ans, arr)
}

return ans
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
package main

import "fmt"
import "container/list"







func main() {
vertices := AdjList{
VNode{
Data: 0,
ArcNodeArr: []ArcNode{
ArcNode{AdjVex: 1},
ArcNode{AdjVex: 2},
},
},
VNode{
Data: 1,
ArcNodeArr: []ArcNode{
ArcNode{AdjVex: 3},
},
},
VNode{
Data: 2,
ArcNodeArr: []ArcNode{
ArcNode{AdjVex: 3},
ArcNode{AdjVex: 4},
},
},
VNode{
Data: 3,
ArcNodeArr: []ArcNode{
ArcNode{AdjVex: 0},
ArcNode{AdjVex: 5},
},
},
VNode{
Data: 4,
ArcNodeArr: []ArcNode{
ArcNode{AdjVex: 5},
},
},
VNode{
Data: 5,
ArcNodeArr: []ArcNode{},
},
}

fmt.Println(makeDotScb(gabow(vertices), vertices))
}
digraph G {
$input
}

12.7 DONE 关键路径

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
func CriticalPath(vertices AdjList) []int {
q := New()
visited := make([]int, len(vertices))
indegree := make([]int, len(vertices))
earlyStart := make([]int, len(vertices))
lateStart := make([]int, len(vertices))

for u := 0; u < len(vertices); u += 1 {
if visited[u] != 1 {
q.Push(u)
visited[u] = 1
for !q.Empty() {
v := q.Pop().(int)
for j := 0; j < len(vertices[v].ArcNodeArr); j += 1 {
w := vertices[v].ArcNodeArr[j].AdjVex
weight := vertices[v].ArcNodeArr[j].Info.(int)
indegree[w] += 1

if earlyStart[v]+weight > earlyStart[w] {
earlyStart[w] = earlyStart[v] + weight
}

if visited[w] != 1 {
q.Push(w)
visited[w] = 1
}
}
}
}
}

tsArr := make([]int, 0)
q = New()
for u := 0; u < len(vertices); u += 1 {
if indegree[u] == 0 {
q.Push(u)
}
}

for !q.Empty() {
u := q.Pop().(int)
tsArr = append(tsArr, u)

for j := 0; j < len(vertices[u].ArcNodeArr); j += 1 {
v := vertices[u].ArcNodeArr[j].AdjVex
indegree[v] -= 1
if indegree[v] == 0 {
q.Push(v)
}
}
}

for i, _ := range lateStart {
lateStart[i] = -1
}
e := tsArr[len(tsArr)-1]
lateStart[e] = earlyStart[e]

for i := len(tsArr) - 2; i >= 0; i -= 1 {
u := tsArr[i]
for j := 0; j < len(vertices[u].ArcNodeArr); j += 1 {
v := vertices[u].ArcNodeArr[j].AdjVex
weight := vertices[u].ArcNodeArr[j].Info.(int)
if lateStart[u] == -1 || lateStart[v]-weight < lateStart[u] {
lateStart[u] = lateStart[v] - weight
}
}
}

ans := make([]int, 0)
for i := 0; i < len(vertices); i += 1 {
if earlyStart[i] == lateStart[i] {
ans = append(ans, i)
}
}

return ans
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
package main

import "fmt"
import "container/list"





func main() {
vertices := AdjList{
VNode{
Data: 0,
ArcNodeArr: []ArcNode{
ArcNode{AdjVex: 1, Info: 3},
ArcNode{AdjVex: 2, Info: 4},
},
},
VNode{
Data: 1,
ArcNodeArr: []ArcNode{
ArcNode{AdjVex: 3, Info: 5},
ArcNode{AdjVex: 4, Info: 6},
},
},
VNode{
Data: 2,
ArcNodeArr: []ArcNode{
ArcNode{AdjVex: 3, Info: 8},
ArcNode{AdjVex: 5, Info: 7},
},
},
VNode{
Data: 3,
ArcNodeArr: []ArcNode{
ArcNode{AdjVex: 4, Info: 3},
},
},
VNode{
Data: 4,
ArcNodeArr: []ArcNode{
ArcNode{AdjVex: 6, Info: 9},
ArcNode{AdjVex: 7, Info: 4},
},
},
VNode{
Data: 5,
ArcNodeArr: []ArcNode{
ArcNode{AdjVex: 7, Info: 6},
},
},
VNode{
Data: 6,
ArcNodeArr: []ArcNode{
ArcNode{AdjVex: 9, Info: 2},
},
},
VNode{
Data: 7,
ArcNodeArr: []ArcNode{
ArcNode{AdjVex: 8, Info: 5},
},
},
VNode{
Data: 8,
ArcNodeArr: []ArcNode{
ArcNode{AdjVex: 9, Info: 3},
},
},
VNode{
Data: 9,
ArcNodeArr: []ArcNode{},
},
}

fmt.Println(CriticalPath(vertices))
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
func CriticalPath(vertices AdjList) ([]int, bool) {
s := New()
var bCycle bool
visited := make([]int, len(vertices))
earlyStart := make([]int, len(vertices))
lateStart := make([]int, len(vertices))

var dfsVisit func(int)
dfsVisit = func(u int) {
visited[u] = 1
for i := 0; i < len(vertices[u].ArcNodeArr); i += 1 {
v := vertices[u].ArcNodeArr[i].AdjVex
weight := vertices[u].ArcNodeArr[i].Info.(int)
if earlyStart[u]+weight > earlyStart[v] {
earlyStart[v] = earlyStart[u] + weight
}
if visited[v] == 1 {
bCycle = true
return
} else if visited[v] != 2 {
dfsVisit(v)
}
}
visited[u] = 2
s.Push(u)
return
}

for u := 0; u < len(vertices); u += 1 {
if visited[u] != 1 {
dfsVisit(u)
}
}

for i, _ := range lateStart {
lateStart[i] = -1
}
e := s.Pop().(int)
lateStart[e] = earlyStart[e]

for !s.Empty() {
u := s.Pop().(int)
for j := 0; j < len(vertices[u].ArcNodeArr); j += 1 {
v := vertices[u].ArcNodeArr[j].AdjVex
weight := vertices[u].ArcNodeArr[j].Info.(int)
if lateStart[u] == -1 || lateStart[v]-weight < lateStart[u] {
lateStart[u] = lateStart[v] - weight
}
}
}

ans := make([]int, 0)
for i := 0; i < len(vertices); i += 1 {
if earlyStart[i] == lateStart[i] {
ans = append(ans, i)
}
}

return ans, bCycle
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
package main

import "fmt"
import "container/list"





func main() {
vertices := AdjList{
VNode{
Data: 0,
ArcNodeArr: []ArcNode{
ArcNode{AdjVex: 1, Info: 3},
ArcNode{AdjVex: 2, Info: 4},
},
},
VNode{
Data: 1,
ArcNodeArr: []ArcNode{
ArcNode{AdjVex: 3, Info: 5},
ArcNode{AdjVex: 4, Info: 6},
},
},
VNode{
Data: 2,
ArcNodeArr: []ArcNode{
ArcNode{AdjVex: 3, Info: 8},
ArcNode{AdjVex: 5, Info: 7},
},
},
VNode{
Data: 3,
ArcNodeArr: []ArcNode{
ArcNode{AdjVex: 4, Info: 3},
},
},
VNode{
Data: 4,
ArcNodeArr: []ArcNode{
ArcNode{AdjVex: 6, Info: 9},
ArcNode{AdjVex: 7, Info: 4},
},
},
VNode{
Data: 5,
ArcNodeArr: []ArcNode{
ArcNode{AdjVex: 7, Info: 6},
},
},
VNode{
Data: 6,
ArcNodeArr: []ArcNode{
ArcNode{AdjVex: 9, Info: 2},
},
},
VNode{
Data: 7,
ArcNodeArr: []ArcNode{
ArcNode{AdjVex: 8, Info: 5},
},
},
VNode{
Data: 8,
ArcNodeArr: []ArcNode{
ArcNode{AdjVex: 9, Info: 3},
},
},
VNode{
Data: 9,
ArcNodeArr: []ArcNode{},
},
}

fmt.Println(CriticalPath(vertices))
}

12.8 DONE 最小生成树

12.8.1 DONE Prim算法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
func mstPrim(vertices AdjList, s int) EdgeList {
visited := make([]int, len(vertices))
dist := make([]int, len(vertices))
parent := make([]int, len(vertices))
for i, _ := range dist {
dist[i] = math.MaxInt32
parent[i] = -1
}
dist[s] = 0

for i := 0; i < len(vertices)-1; i += 1 {
minDist := math.MaxInt32
minIndex := -1
for j := 0; j < len(dist); j += 1 {
if visited[j] == 0 && dist[j] < minDist {
minDist = dist[j]
minIndex = j
}
}

visited[minIndex] = 1

u := minIndex
for j := 0; j < len(vertices[u].ArcNodeArr); j += 1 {
v := vertices[u].ArcNodeArr[j].AdjVex
if visited[v] == 0 {
d := vertices[u].ArcNodeArr[j].Info.(int)
if d < dist[v] {
dist[v] = d
parent[v] = u
}
}
}
}

edges := make(EdgeList, 0)
for i := 0; i < len(parent); i += 1 {
if parent[i] != -1 {
edge := Edge{
Start: i,
End: parent[i],
Weight: dist[i],
}
edges = append(edges, edge)
}
}

return edges
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
package main

import "fmt"
import "math"







func main() {
vertices := AdjList{
VNode{
Data: 0,
ArcNodeArr: []ArcNode{
ArcNode{AdjVex: 1, Info: 3},
ArcNode{AdjVex: 2, Info: 4},
ArcNode{AdjVex: 3, Info: 5},
},
},
VNode{
Data: 1,
ArcNodeArr: []ArcNode{
ArcNode{AdjVex: 0, Info: 3},
ArcNode{AdjVex: 2, Info: 5},
ArcNode{AdjVex: 3, Info: 6},
},
},
VNode{
Data: 2,
ArcNodeArr: []ArcNode{
ArcNode{AdjVex: 0, Info: 4},
ArcNode{AdjVex: 1, Info: 5},
ArcNode{AdjVex: 3, Info: 8},
},
},
VNode{
Data: 3,
ArcNodeArr: []ArcNode{
ArcNode{AdjVex: 0, Info: 5},
ArcNode{AdjVex: 1, Info: 6},
ArcNode{AdjVex: 2, Info: 8},
},
},
}

fmt.Println(mstPrim(vertices, 0))
}

12.8.2 DONE Kruskal算法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
func mstKruskal(edges EdgeList, vexNum int) EdgeList {
var findFunc func([]int, int) int
findFunc = func(parent []int, i int) int {
if parent[i] == -1 {
return i
}
return findFunc(parent, parent[i])
}

unionFunc := func(parent []int, i, j int) {
iSet := findFunc(parent, i)
jSet := findFunc(parent, j)
parent[iSet] = jSet
}

sort.Slice(edges, func(i, j int) bool {
return edges[i].Weight <= edges[j].Weight
})

parent := make([]int, vexNum)
for i, _ := range parent {
parent[i] = -1
}

vcn := 0
ans := make(EdgeList, 0)
for _, edge := range edges {
u := findFunc(parent, edge.Start)
v := findFunc(parent, edge.End)

if u == v {
continue
}

unionFunc(parent, u, v)
ans = append(ans, edge)
vcn += 1
if vcn == vexNum-1 {
break
}
}

return ans
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
package main

import "fmt"
import "sort"





func main() {
edges := []Edge{
Edge{Start: 0, End: 1, Weight: 4},
Edge{Start: 0, End: 7, Weight: 8},
Edge{Start: 1, End: 2, Weight: 8},
Edge{Start: 1, End: 7, Weight: 11},
Edge{Start: 2, End: 3, Weight: 7},
Edge{Start: 2, End: 5, Weight: 4},
Edge{Start: 8, End: 2, Weight: 2},
Edge{Start: 3, End: 4, Weight: 9},
Edge{Start: 3, End: 5, Weight: 14},
Edge{Start: 5, End: 4, Weight: 10},
Edge{Start: 6, End: 5, Weight: 2},
Edge{Start: 8, End: 6, Weight: 6},
Edge{Start: 7, End: 6, Weight: 1},
Edge{Start: 7, End: 8, Weight: 7},
}

fmt.Println(mstKruskal(edges, 9))
}

12.9 DONE 最短路径

12.9.1 DONE 单源最短路径

  • State "DONE" from "TODO" [2018-04-11 Wed 22:41]
  1. DONE Dijkstra算法
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    func dijkstra(vertices AdjList, s int) []int {
    visited := make([]bool, len(vertices))
    dis := make([]int, len(vertices))
    for i, _ := range dis {
    dis[i] = math.MaxInt32
    }
    dis[s] = 0

    for {
    min := math.MaxInt32
    t := -1
    for u := 0; u < len(vertices); u += 1 {
    if !visited[u] && dis[u] < min {
    min = dis[u]
    t = u
    }
    }

    if t == -1 {
    break
    }
    visited[t] = true

    for j := 0; j < len(vertices[t].ArcNodeArr); j += 1 {
    v := vertices[t].ArcNodeArr[j].AdjVex
    d := vertices[t].ArcNodeArr[j].Info.(int)

    if !visited[v] && dis[t]+d < dis[v] {
    dis[v] = dis[t] + d
    }
    }

    }

    return dis
    }
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    package main

    import "fmt"
    import "math"




    func main() {
    vertices := AdjList{
    VNode{
    Data: 0,
    ArcNodeArr: []ArcNode{
    ArcNode{AdjVex: 1, Info: 10},
    ArcNode{AdjVex: 2, Info: 5},
    },
    },
    VNode{
    Data: 1,
    ArcNodeArr: []ArcNode{
    ArcNode{AdjVex: 2, Info: 2},
    ArcNode{AdjVex: 3, Info: 1},
    },
    },
    VNode{
    Data: 2,
    ArcNodeArr: []ArcNode{
    ArcNode{AdjVex: 1, Info: 3},
    ArcNode{AdjVex: 3, Info: 9},
    ArcNode{AdjVex: 4, Info: 2},
    },
    },
    VNode{
    Data: 3,
    ArcNodeArr: []ArcNode{
    ArcNode{AdjVex: 4, Info: 4},
    },
    },
    VNode{
    Data: 4,
    ArcNodeArr: []ArcNode{
    ArcNode{AdjVex: 0, Info: 7},
    ArcNode{AdjVex: 3, Info: 6},
    },
    },
    }

    fmt.Println(dijkstra(vertices, 0))
    }
  2. DONE Bellman–Ford算法
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    func bellmanFord(vertices AdjList, s int) ([]int, bool) {
    dist := make([]int, len(vertices))
    for i, _ := range dist {
    dist[i] = math.MaxInt32
    }
    dist[s] = 0

    for i := 1; i < len(vertices); i += 1 {
    for u := 0; u < len(vertices); u += 1 {
    for j := 0; j < len(vertices[u].ArcNodeArr); j += 1 {
    v := vertices[u].ArcNodeArr[j].AdjVex
    d := vertices[u].ArcNodeArr[j].Info.(int)
    if dist[u]+d < dist[v] {
    dist[v] = dist[u] + d
    }
    }
    }
    }

    for u := 0; u < len(vertices); u += 1 {
    for j := 0; j < len(vertices[u].ArcNodeArr); j += 1 {
    v := vertices[u].ArcNodeArr[j].AdjVex
    d := vertices[u].ArcNodeArr[j].Info.(int)
    if dist[u]+d < dist[v] {
    return dist, true
    }
    }
    }

    return dist, false
    }
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    package main

    import "fmt"
    import "math"





    func main() {
    vertices := AdjList{
    VNode{
    Data: 0,
    ArcNodeArr: []ArcNode{
    ArcNode{AdjVex: 1, Info: 10},
    ArcNode{AdjVex: 2, Info: 5},
    },
    },
    VNode{
    Data: 1,
    ArcNodeArr: []ArcNode{
    ArcNode{AdjVex: 2, Info: 2},
    ArcNode{AdjVex: 3, Info: 1},
    },
    },
    VNode{
    Data: 2,
    ArcNodeArr: []ArcNode{
    ArcNode{AdjVex: 1, Info: 3},
    ArcNode{AdjVex: 3, Info: 9},
    ArcNode{AdjVex: 4, Info: 2},
    },
    },
    VNode{
    Data: 3,
    ArcNodeArr: []ArcNode{
    ArcNode{AdjVex: 4, Info: 4},
    },
    },
    VNode{
    Data: 4,
    ArcNodeArr: []ArcNode{
    ArcNode{AdjVex: 0, Info: 7},
    ArcNode{AdjVex: 3, Info: 6},
    },
    },
    }

    fmt.Println(bellmanFord(vertices, 0))
    }

12.9.2 DONE 每对顶点间的最短路径

  • State "DONE" from "TODO" [2018-04-11 Wed 22:43]
  1. DONE Floyd-Warshall算法
    • State "DONE" from "TODO" [2018-04-11 Wed 17:18]
    1. DONE 原理描述
      • State "DONE" from "TODO" [2018-04-11 Wed 16:47]

      Floyd-Warshall算法的原理是动态规划。 设 D{i,j,k}为从 i到 j的只以 (1..k)集合中的节点为中间节点的最短路径的长度。

      若最短路径经过点k,则 D{i,j,k}=D{i,k,k-1}+D{k,j,k-1}; 若最短路径不经过点k,则 D{i,j,k}=D{i,j,k-1}。 因此, D{i,j,k}=min(D{i,j,k-1},D{i,k,k-1}+D{k,j,k-1})。

      在实际算法中,为了节约空间,可以直接在原来空间上进行迭代,这样空间可降至二维。

    2. DONE 算法实现
      • State "DONE" from "TODO" [2018-04-11 Wed 17:18]
      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      20
      21
      22
      23
      24
      25
      26
      27
      28
      29
      30
      func floydWarshall(vertices AdjList) [][]int {
      dist := make([][]int, len(vertices))
      for i, _ := range dist {
      dist[i] = make([]int, len(vertices))
      for j, _ := range dist[i] {
      dist[i][j] = math.MaxInt32
      }
      dist[i][i] = 0
      }

      for u := 0; u < len(vertices); u += 1 {
      for j := 0; j < len(vertices[u].ArcNodeArr); j += 1 {
      v := vertices[u].ArcNodeArr[j].AdjVex
      d := vertices[u].ArcNodeArr[j].Info.(int)
      dist[u][v] = d
      }
      }

      for k := 0; k < len(vertices); k += 1 {
      for i := 0; i < len(vertices); i += 1 {
      for j := 0; j < len(vertices); j += 1 {
      if dist[i][j] > dist[i][k]+dist[k][j] {
      dist[i][j] = dist[i][k] + dist[k][j]
      }
      }
      }
      }

      return dist
      }
      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      20
      21
      22
      23
      24
      25
      26
      27
      28
      29
      30
      31
      32
      33
      34
      35
      36
      37
      38
      39
      40
      41
      42
      43
      44
      45
      46
      47
      48
      49
      package main

      import "fmt"
      import "math"




      func main() {
      vertices := AdjList{
      VNode{
      Data: 0,
      ArcNodeArr: []ArcNode{
      ArcNode{AdjVex: 1, Info: 10},
      ArcNode{AdjVex: 2, Info: 5},
      },
      },
      VNode{
      Data: 1,
      ArcNodeArr: []ArcNode{
      ArcNode{AdjVex: 2, Info: 2},
      ArcNode{AdjVex: 3, Info: 1},
      },
      },
      VNode{
      Data: 2,
      ArcNodeArr: []ArcNode{
      ArcNode{AdjVex: 1, Info: 3},
      ArcNode{AdjVex: 3, Info: 9},
      ArcNode{AdjVex: 4, Info: 2},
      },
      },
      VNode{
      Data: 3,
      ArcNodeArr: []ArcNode{
      ArcNode{AdjVex: 4, Info: -4},
      },
      },
      VNode{
      Data: 4,
      ArcNodeArr: []ArcNode{
      ArcNode{AdjVex: 0, Info: 7},
      ArcNode{AdjVex: 3, Info: 6},
      },
      },
      }

      fmt.Println(floydWarshall(vertices))
      }
  2. DONE Johnson算法
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    func johnson(vertices AdjList) ([][]int, bool) {
    v := VNode{
    Data: len(vertices),
    ArcNodeArr: make([]ArcNode, len(vertices)),
    }

    for i, _ := range vertices {
    v.ArcNodeArr[i] = ArcNode{
    AdjVex: i,
    Info: 0,
    }
    }
    vertices = append(vertices, v)

    hDist, bCycle := bellmanFord(vertices, len(vertices)-1)
    if bCycle {
    return [][]int{}, bCycle
    }

    for u := 0; u < len(vertices); u += 1 {
    for j := 0; j < len(vertices[u].ArcNodeArr); j += 1 {
    v := vertices[u].ArcNodeArr[j].AdjVex
    d := vertices[u].ArcNodeArr[j].Info.(int)
    d = d + (hDist[u] - hDist[v])
    vertices[u].ArcNodeArr[j].Info = d
    }
    }

    vertices = vertices[:len(vertices)-1]
    dist := make([][]int, len(vertices))
    for i, _ := range vertices {
    dist[i] = dijkstra(vertices, i)
    for j, _ := range dist[i] {
    dist[i][j] = dist[i][j] + (hDist[j] - hDist[i])
    }
    }

    return dist, false
    }
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    package main

    import "fmt"
    import "math"









    func main() {
    vertices := AdjList{
    VNode{
    Data: 0,
    ArcNodeArr: []ArcNode{
    ArcNode{AdjVex: 1, Info: 10},
    ArcNode{AdjVex: 2, Info: 5},
    },
    },
    VNode{
    Data: 1,
    ArcNodeArr: []ArcNode{
    ArcNode{AdjVex: 2, Info: 2},
    ArcNode{AdjVex: 3, Info: 1},
    },
    },
    VNode{
    Data: 2,
    ArcNodeArr: []ArcNode{
    ArcNode{AdjVex: 1, Info: 3},
    ArcNode{AdjVex: 3, Info: 9},
    ArcNode{AdjVex: 4, Info: 2},
    },
    },
    VNode{
    Data: 3,
    ArcNodeArr: []ArcNode{
    ArcNode{AdjVex: 4, Info: -4},
    },
    },
    VNode{
    Data: 4,
    ArcNodeArr: []ArcNode{
    ArcNode{AdjVex: 0, Info: 7},
    ArcNode{AdjVex: 3, Info: 6},
    },
    },
    }

    fmt.Println(johnson(vertices))
    }

13 DONE Cache

  • State "DONE" from "TODO" [2018-03-23 Fri 17:46]

13.1 DONE LRU

  • State "DONE" from "TODO" [2018-03-23 Fri 17:45]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
type MyListNode struct {
Key int
Value int
Next *MyListNode
}

type LRUCache struct {
Capacity int
Head *MyListNode
}

func Constructor(capacity int) LRUCache {
return LRUCache{
Capacity: capacity,
Head: nil,
}
}

func (this *LRUCache) Get(key int) int {
dummyNode := &MyListNode{
Next: this.Head,
}

pre := dummyNode
curr := dummyNode.Next
for curr != nil {
if curr.Key == key {
pre.Next = curr.Next
curr.Next = dummyNode.Next
dummyNode.Next = curr
this.Head = dummyNode.Next
return dummyNode.Next.Value
}

pre = curr
curr = curr.Next
}

return -1
}

func (this *LRUCache) Put(key int, value int) {
newNode := &MyListNode{
Key: key,
Value: value,
}
if this.Head == nil {
this.Head = newNode
return
}

dummyNode := &MyListNode{
Next: this.Head,
}

var length int
pre := dummyNode
curr := dummyNode.Next
for curr != nil {
if curr.Key == key {
pre.Next = curr.Next
curr.Next = dummyNode.Next
dummyNode.Next = curr
curr.Value = value
this.Head = dummyNode.Next
return
}

pre = curr
curr = curr.Next
length += 1
}

if length == this.Capacity {
curr = dummyNode
for length > 1 {
curr = curr.Next
length -= 1
}
curr.Next = nil
}

newNode.Next = dummyNode.Next
dummyNode.Next = newNode
this.Head = dummyNode.Next
return
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
type MyListNode struct {
Key int
Value int
Pre *MyListNode
Next *MyListNode
}

type LRUCache struct {
Capacity int
Length int
Head *MyListNode
Tail *MyListNode
K2NodeMap map[int]*MyListNode
}

func Constructor(capacity int) LRUCache {
return LRUCache{
Capacity: capacity,
Length: 0,
K2NodeMap: make(map[int]*MyListNode),
}
}

func (this *LRUCache) Get(key int) int {
targetNode := this.getNode(key)
if targetNode != nil {
return targetNode.Value
} else {
return -1
}
}

func (this *LRUCache) getNode(key int) *MyListNode {
if this.Length == 0 {
return nil
}

if targetNode, ok := this.K2NodeMap[key]; ok {
if targetNode == this.Head {
return targetNode
}

if targetNode.Pre != nil {
targetNode.Pre.Next = targetNode.Next
}
if targetNode.Next != nil {
targetNode.Next.Pre = targetNode.Pre
}

if this.Tail == targetNode {
this.Tail = targetNode.Pre
if this.Tail != nil {
this.Tail.Next = nil
}
}

targetNode.Next = this.Head
if this.Head != nil {
this.Head.Pre = targetNode
}
this.Head = targetNode
targetNode.Pre = nil
if this.Length == 1 {
this.Tail = targetNode
}
return targetNode
} else {
return nil
}
}

func (this *LRUCache) Put(key int, value int) {
if this.Capacity == 0 {
return
}

targetNode := this.getNode(key)
if targetNode != nil {
targetNode.Value = value
return
}

newNode := &MyListNode{
Key: key,
Value: value,
}
if this.Head == nil {
this.Length = 1
this.Head = newNode
this.Tail = newNode
this.K2NodeMap[newNode.Key] = newNode
return
}

if this.Length == this.Capacity {
delete(this.K2NodeMap, this.Tail.Key)
if this.Tail.Pre != nil {
this.Tail = this.Tail.Pre
this.Tail.Next = nil
} else {
this.Head, this.Tail = nil, nil
}
} else {
this.Length += 1
}

this.K2NodeMap[newNode.Key] = newNode
newNode.Next = this.Head
if this.Head != nil {
this.Head.Pre = newNode
}
this.Head = newNode
if this.Length == 1 {
this.Tail = newNode
}

return
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
package main

import "fmt"



func main() {
lru := Constructor(2)
lru.Put(2, 1)
lru.Put(3, 2)
fmt.Println(lru.Get(2))
fmt.Println(lru.Get(3))
fmt.Println(lru.Get(3))
lru.Put(4, 3)
fmt.Println(lru.Get(2))
fmt.Println(lru.Get(3))
fmt.Println(lru.Get(4))
return
}

13.2 DONE LFU

  • State "DONE" from "TODO" [2018-03-23 Fri 13:54]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
type MyListNode struct {
Key int
Value int
Counter int
Next *MyListNode
}

type LFUCache struct {
Capacity int
Head *MyListNode
}

func Constructor(capacity int) LFUCache {
return LFUCache{
Capacity: capacity,
Head: nil,
}
}

func (this *LFUCache) Get(key int) int {
if this.Capacity == 0 {
return -1
}

dummyNode := &MyListNode{
Next: this.Head,
}

pre := dummyNode
curr := this.Head
for curr != nil {
if curr.Key == key {
curr.Counter += 1
pre.Next = curr.Next
curr.Next = dummyNode.Next
dummyNode.Next = curr
this.Head = dummyNode.Next
return dummyNode.Next.Value
}

pre = curr
curr = curr.Next
}

return -1
}

func (this *LFUCache) Put(key int, value int) {
if this.Capacity == 0 {
return
}

newNode := &MyListNode{
Key: key,
Value: value,
Counter: 1,
}
if this.Head == nil {
this.Head = newNode
return
}

dummyNode := &MyListNode{
Next: this.Head,
}

var length int
pre := dummyNode
curr := dummyNode.Next
min_pre, min_curr := pre, curr
for curr != nil {
if curr.Key == key {
curr.Counter += 1
curr.Value = value
pre.Next = curr.Next
curr.Next = dummyNode.Next
dummyNode.Next = curr
curr.Value = value
this.Head = dummyNode.Next
return
}

if min_curr.Counter >= curr.Counter {
min_pre, min_curr = pre, curr
}

pre = curr
curr = curr.Next
length += 1
}

if length == this.Capacity {
min_pre.Next = min_curr.Next
}

newNode.Next = dummyNode.Next
dummyNode.Next = newNode
this.Head = dummyNode.Next
return
}
Last Updated 2018-04-26 Thu 18:42.
Render by hexo-renderer-org with Emacs 25.3.2 (Org mode 8.2.10)

Leetcode-dynamic-programming

发表于 2018-03-11 | 分类于 技术积累 |

1 DONE Min Cost Climbing Stairs

  • State "DONE" from "TODO" [2018-03-12 Mon 11:14]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
func min(a, b int) int {
if a > b {
return b
} else {
return a
}
}
func minCostClimbingStairs(cost []int) int {
min_cost_arr := make([]int, len(cost))
min_cost_arr[0] = cost[0]
min_cost_arr[1] = cost[1]
for index := 2; index < len(cost); index += 1 {
min_cost_arr[index] = min(min_cost_arr[index-2],
min_cost_arr[index-1])+cost[index]
}

return min(min_cost_arr[len(cost)-1], min_cost_arr[len(cost)-2])
}

2 DONE Climbing Stairs

  • State "DONE" from "TODO" [2018-03-12 Mon 11:26]
1
2
3
4
5
6
7
8
9
10
11
12
13
func climbStairs(n int) int {
if n < 3 {
return n
}
s_ways := make([]int, n)
s_ways[0] = 1
s_ways[1] = 2
for index := 2; index < n; index += 1 {
s_ways[index] = s_ways[index-1] + s_ways[index-2]
}

return s_ways[n-1]
}

3 DONE House Robber

  • State "DONE" from "TODO" [2018-03-12 Mon 14:17]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
func max(a, b int) int {
if a > b {
return a
} else {
return b
}
}

func rob(nums []int) int {
if len(nums) < 1 {
return 0
}

rob_nums := make([][]int, len(nums))
for index, _ := range rob_nums {
rob_nums[index] = make([]int, 2)
}
rob_nums[0][0] = nums[0]
rob_nums[0][1] = 0
for index := 1; index < len(nums); index += 1 {
rob_nums[index][0] = rob_nums[index-1][1] + nums[index]
rob_nums[index][1] = max(rob_nums[index-1][0], rob_nums[index-1][1])
}

return max(rob_nums[len(nums)-1][0], rob_nums[len(nums)-1][1])
}

4 DONE House Robber II

  • State "DONE" from "TODO" [2018-03-14 Wed 16:33]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
func max(a, b int) int {
if a > b {
return a
} else {
return b
}
}

func robS(nums []int) int {
if len(nums) < 1 {
return 0
}

rob_nums := make([][]int, len(nums))
for index, _ := range rob_nums {
rob_nums[index] = make([]int, 2)
}
rob_nums[0][0] = nums[0]
rob_nums[0][1] = 0
for index := 1; index < len(nums); index += 1 {
rob_nums[index][0] = rob_nums[index-1][1] + nums[index]
rob_nums[index][1] = max(rob_nums[index-1][0], rob_nums[index-1][1])
}

return max(rob_nums[len(nums)-1][0], rob_nums[len(nums)-1][1])
}

func rob(nums []int) int {
if len(nums) < 1 {
return 0
}

if len(nums) == 1 {
return nums[0]
}

return max(robS(nums[1:]), robS(nums[0:len(nums)-1]))
}

5 DONE Range Sum Query - Immutable

  • State "DONE" from "TODO" [2018-03-12 Mon 14:44]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
type NumArray struct {
sums []int
}

func Constructor(nums []int) NumArray {
if len(nums) < 2 {
return NumArray{
sums: nums,
}
}

sums := make([]int, len(nums))
sums[0] = nums[0]
for index := 1; index < len(nums); index += 1 {
sums[index] = sums[index-1] + nums[index]
}

return NumArray{
sums: sums,
}
}

func (this *NumArray) SumRange(i int, j int) int {
if len(this.sums) < 1 {
return 0
}
if i == 0 {
return this.sums[j]
} else {
return this.sums[j] - this.sums[i-1]
}
}

6 DONE Counting Bits

  • State "DONE" from "TODO" [2018-03-12 Mon 16:22]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
func countBits(num int) []int {
if num < 1 {
return []int{0}
}

if num == 1 {
return []int{0, 1}
}

bit_nums := make([]int, 0)
bit_nums[0] = 0
bit_nums[1] = 1
index := 1
for index < num {
index *= 2
bit_nums[index] = 1
for i := 1; i < index && i+index <= num; i += 1 {
bit_nums[index+i] = 1 + bit_nums[i]
}
}

return bit_nums
}

7 DONE Palindromic Substrings

  • State "DONE" from "TODO" [2018-03-12 Mon 18:20]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
func countSubstrings(s string) int {
if len(s) < 1 {
return 0
}
subStrs := make([]int, len(s))
subStrs[0] = 1
for i := 1; i < len(s); i += 1 {
subStrs[i] = subStrs[i-1] + 1
for j := i - 1; j >= 0; j -= 1 {
if isPalindromic(s[j : i+1]) {
subStrs[i] += 1
}
}
}

return subStrs[len(s)-1]
}

func isPalindromic(s string) bool {
for i := 0; i < len(s)/2; i += 1 {
if s[i] != s[len(s)-1-i] {
return false
}
}

return true
}

8 DONE Minimum ASCII Delete Sum for Two Strings

  • State "DONE" from "TODO" [2018-03-13 Tue 22:04]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
func min(a, b int) int {
if a > b {
return b
} else {
return a
}
}
func minimumDeleteSum(s1 string, s2 string) int {
dps := make([][]int, len(s1)+1)
for i, _ := range dps {
dps[i] = make([]int, len(s2)+1)
}

for i := len(s1) - 1; i >= 0; i -= 1 {
dps[i][len(s2)] = dps[i+1][len(s2)] + int(s1[i])
}

for i := len(s2) - 1; i >= 0; i -= 1 {
dps[len(s1)][i] = dps[len(s1)][i+1] + int(s2[i])
}

for i := len(s1) - 1; i >= 0; i -= 1 {
for j := len(s2) - 1; j >= 0; j -= 1 {
if s1[i] == s2[j] {
dps[i][j] = dps[i+1][j+1]
} else {
dps[i][j] = min(
dps[i+1][j]+int(s1[i]),
dps[i][j+1]+int(s2[j]))
}
}
}

return dps[0][0]
}

9 DONE Arithmetic Slices

  • State "DONE" from "TODO" [2018-03-12 Mon 17:31]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
type ASStatus struct {
Num int
InAs bool
SizeOfAs int
DiffNum int
}

func numberOfArithmeticSlices(A []int) int {
if len(A) < 3 {
return 0
}

ass_arr := make([]*ASStatus, len(A))
ass_arr[0] = &ASStatus{}
ass_arr[1] = &ASStatus{}
for i := 2; i < len(A); i += 1 {
if ass_arr[i-1].InAs {
if A[i]-A[i-1] == ass_arr[i-1].DiffNum {
ass_arr[i] = &ASStatus{
Num: ass_arr[i-1].Num + ass_arr[i-1].SizeOfAs - 1,
InAs: true,
SizeOfAs: ass_arr[i-1].SizeOfAs + 1,
DiffNum: ass_arr[i-1].DiffNum,
}
} else {
ass_arr[i] = &ASStatus{
Num: ass_arr[i-1].Num,
}
}
} else {
if A[i]-A[i-1] == A[i-1]-A[i-2] {
ass_arr[i] = &ASStatus{
Num: ass_arr[i-1].Num + 1,
InAs: true,
SizeOfAs: 3,
DiffNum: A[i] - A[i-1],
}
} else {
ass_arr[i] = &ASStatus{
Num: ass_arr[i-1].Num,
}
}
}
}

return ass_arr[len(A)-1].Num
}
1
2
3
4
5
6
7
8
9
10
11
12
func numberOfArithmeticSlices(A []int) int {
dp := make([]int, len(A))
var sum int
for i = 2; i < len(A); i += 1 {
if A[i]-A[i-1] == A[i-1]-A[i-2] {
dp[i] = 1 + dp[i-1]
sum += dp[i]
}
}

return sum
}

10 TODO Arithmetic Slices II - Subsequence

1
2
func numberOfArithmeticSlices(A []int) int {
}

11 DONE Maximum Length of Pair Chain

  • State "DONE" from "TODO" [2018-03-12 Mon 23:01]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
import "sort"

func max(a, b int) int {
if a > b {
return a
} else {
return b
}
}
func findLongestChain(pairs [][]int) int {
if len(pairs) < 2 {
return len(pairs)
}

sort.Slice(
pairs,
func(i, j int) bool {
return pairs[i][0] < pairs[j][0]
})
dps := make([]int, len(pairs))
for i, _ := range dps {
dps[i] = 1
}

for i := 1; i < len(pairs); i += 1 {
for j := 0; j < i; j += 1 {
if pairs[j][1] < pairs[i][0] {
dps[i] = max(dps[j]+1, dps[i])
}
}
}

mx := 0
for _, dp := range dps {
if dp > mx {
mx = dp
}
}

return mx
}

12 DONE Integer Break

  • State "DONE" from "TODO" [2018-03-13 Tue 12:00]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
func integerBreak(n int) int {
if n < 3 {
return 1
}

if n == 3 {
return 2
}

k := math.Floor(float64(n) / 3.0)
r = n % 3
if r == 0 {
return int(math.Pow(3.0, k))
} else if r == 1 {
return 4 * int(math.Pow(3.0, k-1))
} else {
return 2 * int(math.Pow(3.0, k))
}
}

13 DONE LCS

  • State "DONE" from "TODO" [2018-03-13 Tue 18:32]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
func max(a, b int) int {
if a > b {
return a
} else {
return b
}
}

func LCS(lstr, rstr string) string {
dps := make([][]int, len(lstr)+1)
for i, _ := range dps {
dps[i] = make([]int, len(rstr)+1)
}

for i := 1; i <= len(lstr); i += 1 {
for j := 1; j <= len(rstr); j += 1 {
if lstr[i-1] == rstr[j-1] {
dps[i][j] = dps[i-1][j-1] + 1
} else {
dps[i][j] = max(dps[i-1][j], dps[i][j-1])
}
}
}

byteLCS := make([]byte, dps[len(lstr)][len(rstr)])
i := len(lstr)
j := len(rstr)
for i > 0 && j > 0 {
if lstr[i-1] == rstr[j-1] {
byteLCS[dps[i][j]-1] = lstr[i-1]
i -= 1
j -= 1
} else if dps[i-1][j] > dps[i][j-1] {
i -= 1
} else {
j -= 1
}
}

return string(byteLCS)
}
"main no"body

14 DONE Count Numbers with Unique Digits

  • State "DONE" from "TODO" [2018-03-13 Tue 23:10]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
func countNumbersWithUniqueDigits(n int) int {
if n == 0 {
return 1
}

dps := make([]int, n+1)
dps[0] = 1
dps[1] = 9
for i := 2; i <= n; i += 1 {
if i > 9 {
dps[i] = 0
} else {
dps[i] = dps[i-1] * (11 - i)
}
}

c := 0
for _, dp := range dps {
c += dp
}

return c
}

15 DONE Longest Increasing Subsequence

  • State "DONE" from "TODO" [2018-03-14 Wed 11:43]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
func max(a, b int) int {
if a > b {
return a
} else {
return b
}
}

func lengthOfLIS(nums []int) int {
if len(nums) < 1 {
return 0
}

dp := make([]int, len(nums))
dp[0] = 1
maxAns := 1
for i := 1; i < len(nums); i += 1 {
var maxVal int
for j := 0; j < i; j += 1 {
if nums[i] > nums[j] {
maxVal = max(maxVal, dp[j])
}
}
dp[i] = maxVal + 1
maxAns = max(maxAns, dp[i])
}

return maxAns
}

16 DONE Number of Longest Increasing Subsequence

  • State "DONE" from "TODO" [2018-03-14 Wed 12:05]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
func max(a, b int) int {
if a > b {
return a
} else {
return b
}
}

func findNumberOfLIS(nums []int) int {
if len(nums) < 2 {
return len(nums)
}

lengths := make([]int, len(nums))
counts := make([]int, len(nums))
for i, _ := range counts {
counts[i] = 1
}

lengths[0] = 1
maxAns := 1
for i := 1; i < len(nums); i += 1 {
var maxVal int
for j := 0; j < i; j += 1 {
if nums[i] > nums[j] {
if lengths[j] > maxVal {
counts[i] = counts[j]
maxVal = lengths[j]
} else if lengths[j] == maxVal {
counts[i] += counts[j]
}
}
}
lengths[i] = maxVal + 1
maxAns = max(maxAns, lengths[i])
}

var sum int
for i, _ := range lengths {
if lengths[i] == maxAns {
sum += counts[i]
}
}

return sum
}

17 DONE Longest Palindromic Substring

  • State "DONE" from "TODO" [2018-03-14 Wed 15:51]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
package main

import "fmt"

func max(a, b int) int {
if a > b {
return a
} else {
return b
}
}

func longestPalindrome(s string) string {
var start, end int
for i := 0; i < len(s); i += 1 {
length_s := expandAroundCenter(s, i, i)
length_d := expandAroundCenter(s, i, i+1)
length := max(length_s, length_d)
if length > end-start {
start = i - (length-1)/2
end = i + length/2
}
}

return s[start : end+1]
}

func expandAroundCenter(s string, left, right int) int {
l, r := left, right
for l >= 0 && r < len(s) && s[l] == s[r] {
l -= 1
r += 1
}

return r - l - 1
}

func main() {
fmt.Println(longestPalindrome("abacdfgdcaba"))
}

18 DONE Longest Palindromic Subsequence

  • State "DONE" from "TODO" [2018-03-14 Wed 16:01]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
func reverse(s string) string {
r := []rune(s)
for i, j := 0, len(r)-1; i < len(r)/2; i, j = i+1, j-1 {
r[i], r[j] = r[j], r[i]
}
return string(r)
}

func max(a, b int) int {
if a > b {
return a
} else {
return b
}
}

func lengthOfLCS(lstr, rstr string) int {
dps := make([][]int, len(lstr)+1)
for i, _ := range dps {
dps[i] = make([]int, len(rstr)+1)
}

for i := 1; i <= len(lstr); i += 1 {
for j := 1; j <= len(rstr); j += 1 {
if lstr[i-1] == rstr[j-1] {
dps[i][j] = dps[i-1][j-1] + 1
} else {
dps[i][j] = max(dps[i-1][j], dps[i][j-1])
}
}
}

return dps[len(lstr)][len(rstr)]
}

func longestPalindromeSubseq(s string) int {
return lengthOfLCS(s, reverse(s))
}

19 WAITING Predict the Winner

  • State "WAITING" from "TODO" [2018-03-14 Wed 18:05]
    minimax算法学习
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
func max(a, b int) int {
if a > b {
return a
} else {
return b
}
}

func PredictTheWinner(nums []int) bool {
return winner(nums, 1) >= 0
}

func winner(nums []int, turn int) int {
if len(nums) == 1 {
return turn * nums[0]
}

s := turn*nums[0] + winner(nums[1:], -turn)
e := turn*nums[len(nums)-1] + winner(nums[0:len(nums)-2], -turn)

return turn * max(turn*s, turn*e)
}

20 DONE Best Time to Buy and Sell Stock with Cooldown

  • State "DONE" from "TODO" [2018-03-15 Thu 18:25]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
func max(a, b int) int {
if a > b {
return a
} else {
return b
}
}

func maxProfit(prices []int) int {
if len(prices) < 2 {
return 0
}

sell, buy, prev_sell, prev_buy = 0, -prices[0], 0, 0
for _, price := range prices {
prev_buy = buy
buy = max(prev_sell-price, prev_buy)
prev_sell = sell
sell = max(prev_buy+price, prev_sell)
}

return sell
}

21 DONE Best Time to Buy and Sell Stock with Transaction Fee

  • State "DONE" from "TODO" [2018-03-15 Thu 17:14]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
package main

import "fmt"

func max(a, b int) int {
if a > b {
return a
} else {
return b
}
}

func maxProfit(prices []int, fee int) int {
if len(prices) < 2 {
return 0
}

cash, hold := 0, -prices[0]
for i := 1; i < len(prices); i += 1 {
cash = max(cash, hold+prices[i]-fee)
hold = max(hold, cash-prices[i])
}

return cash
}

func main() {
fmt.Println(maxProfit([]int{1, 3, 2, 5, 8, 4, 9, 3}, 2))
}

22 DONE Is Subsequence

  • State "DONE" from "TODO" [2018-03-14 Wed 18:19]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
func isSubsequence(s string, t string) bool {
if len(s) < 1 {
return true
}

if len(s) > len(t) {
return false
}

s_i := 0
for t_i, _ := range t {
if t[t_i] == s[s_i] {
s_i += 1
}
if s_i == len(s) {
break
}
}

return s_i == len(s)
}

23 WAITING Knapsack problem(背包问题)

  • State "WAITING" from "TODO" [2018-03-15 Thu 15:12]
    背包算法,需要好好研究
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
package main

import "fmt"

func max(a, b int) int {
if a > b {
return a
} else {
return b
}
}

func knap(weights []int, values []int, capacity int) int {
dps := make([][]int, len(weights)+1)
for i, _ := range dps {
dps[i] = make([]int, capacity+1)
}

for i := 1; i < len(weights)+1; i += 1 {
for j := 0; j <= capacity; j += 1 {
if j < weights[i-1] {
dps[i][j] = dps[i-1][j]
} else {
dps[i][j] = max(dps[i-1][j], dps[i-1][j-weights[i-1]]+values[i-1])
}
}
}

for _, dp := range dps {
fmt.Println(dp)
}

return dps[len(weights)][capacity]
}

func main() {
fmt.Println(knap([]int{5, 4, 7, 2, 6}, []int{12, 3, 10, 3, 6}, 15))
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
package main

import "fmt"

func max(a, b int) int {
if a > b {
return a
} else {
return b
}
}

func knap(weights []int, values []int, capacity int) int {
dp := make([]int, capacity+1)

for i := 1; i < len(weights)+1; i += 1 {
for j := capacity; j >= weights[i-1]; j -= 1 {
dp[j] = max(dp[j], dp[j-weights[i-1]]+values[i-1])
}
fmt.Println(dp)
}

return dp[capacity]
}

func main() {
fmt.Println(knap([]int{5, 4, 7, 2, 6}, []int{12, 3, 10, 3, 6}, 15))
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
package main

import "fmt"

func max(a, b int) int {
if a > b {
return a
} else {
return b
}
}

func knap(weights []int, values []int, capacity int) int {
dp := make([]int, capacity+1)
for i := 1; i <= capacity; i += 1 {
dp[i] = -10000
}

for i := 1; i < len(weights)+1; i += 1 {
for j := capacity; j >= weights[i-1]; j -= 1 {
dp[j] = max(dp[j], dp[j-weights[i-1]]+values[i-1])
}
fmt.Println(dp)
}

return dp[capacity]
}

func main() {
fmt.Println(knap([]int{5, 4, 7, 2, 6}, []int{12, 3, 10, 3, 6}, 15))
}

24 DONE Maximum Length of Repeated Subarray

  • State "DONE" from "TODO" [2018-03-16 Fri 11:00]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
func findLength(A []int, B []int) int {
dps := make([][]int, len(A)+1)
for i, _ := range dps {
dps[i] = make([]int, len(B)+1)
}

maxAns := 0
for i := 1; i <= len(A); i += 1 {
for j := 1; j <= len(B); j += 1 {
if A[i-1] == B[j-1] {
dps[i][j] = dps[i-1][j-1] + 1
} else {
dps[i][j] = 0
}

if dps[i][j] > maxAns {
maxAns = dps[i][j]
}
}
}

return maxAns
}

25 DONE Coin Change

  • State "DONE" from "TODO" [2018-03-16 Fri 15:20]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
func coinChange(coins []int, amount int) int {
if len(coins) < 1 {
return -1
}
if amount == 0 {
return 0
}

dp := make([]int, amount+1)
for i, _ := range dp {
dp[i] = -1
}

sort.Ints(coins)
for _, coin := range coins {
if coin <= amount {
dp[coin] = 1
}
}

for i := 1; i <= amount; i += 1 {
if dp[i] == 1 {
continue
}

for j := len(coins) - 1; j >= 0; j -= 1 {
coin := coins[j]
if coin > i {
continue
}

if dp[i-coin] > 0 {
if dp[i] == -1 || dp[i] > dp[i-coin]+dp[coin] {
dp[i] = dp[i-coin] + dp[coin]
}
}
}
}

return dp[amount]
}

26 DONE 2 Keys Keyboard

  • State "DONE" from "TODO" [2018-03-16 Fri 17:54]
1
2
3
4
5
6
7
8
9
10
11
12
func minSteps(n int) int {
ans, d := 0, 2
for n > 1 {
for n%d == 0 {
ans += d
n /= d
}
d += 1
}

return ans
}

27 DONE Shopping Offers

  • State "DONE" from "TODO" [2018-03-16 Fri 18:20]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
func shoppingOffers(price []int, special [][]int, needs []int) int {
var ans int
for i := 0; i < len(price); i += 1 {
ans += price[i] * needs[i]
}

for i := 0; i < len(special); i += 1 {
c_needs := make([]int, len(needs))
copy(c_needs, needs)
j := 0
for j = 0; j < len(needs); j += 1 {
rest := needs[j] - special[i][j]
if rest < 0 {
break
}
c_needs[j] = rest
}

if j == len(needs) {
ans = min(ans, c_needs[i][j]+shoppingOffers(price, special, c_needs))
}
}

return ans
}

func min(a, b int) int {
if a > b {
return b
} else {
return a
}
}
Last Updated 2018-04-25 Wed 22:17.
Render by hexo-renderer-org with Emacs 25.3.2 (Org mode 8.2.10)

正则表达式--探索rx宏

发表于 2018-03-01 | 分类于 技术积累 |

原文地址: Regular Expression,你喜欢阅读原汁原味的,请阅读原文 。本文只做学习之用。

Some people, when confronted with a problem, think "I know, I'll use regular expressions." Now they have two problems. - Jamie Zawinski

最近一直忙于crystal-mode的扩展与维护工作,说实话,真不容易,特别是正则表达式部分,太难阅读。 所以我准备把之前的正则表达式,改造成更可读的 s-expression 形式的,这样的话,维护起来就能简单很多。 rx 宏更好能很好的满足要实现的目标。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
(require 's)  ;; All we need is =s-matches-p=
(require 'rx)

;; Creating a regexp that will match -> <File> [<Line>:<Column] <Suggestion>
(setq this-file-name "regular-expression.org")

(s-matches-p
(rx bol
(eval this-file-name)
space
"[" (group (one-or-more digit)) ":" (group (one-or-more digit)) "]"
space
(group (zero-or-more anything))
eol)

"blog.org [17:16] Emacs Lisp, not emacs lisp")


;; Produced regexp, I do not want to write or maintain this by hand
"^blog\\.org[[:space:]]\\[\\([[:digit:]]+\\):\\([[:digit:]]+\\)][[:space:]]\\(\\(?:.\\|
\\)*\\)$"

虽然不那么简洁,但上面的示例很好的说明了在更高抽象等级下编写正则表达式的优点:更易于理解,写起来更舒适,更容易维护。 同时,使用符号表达式的形式更符合emacs的气质。

1 Strings And Quoting

STRING
     matches string STRING literally.

CHAR
     matches character CHAR literally.

‘(eval FORM)’
     evaluate FORM and insert result.  If result is a string,
     ‘regexp-quote’ it.

问题:什么样的正则表达式匹配这个字符串: ASCII表中的标点字符: !"#$%&'()*+,-./:;<=>?@[\]^`{|}

1
2
3
4
5
6
7
8
9
10
;; Escape the double quote here
(setq input "The punctuation characters in the ASCII table are: !\"#$%&'()*+,-./:;<=>?@[\]^_`{|}")

(s-matches-p (rx "The punctuation characters in the ASCII table are: !\"#$%&'()*+,-./:;<=>?@[\]^_`{|}")
input) ;; Direct use of strings


(not (s-matches-p input input)) ;; Does not work because of quoting
(s-matches-p (regexp-quote input) input)

(s-matches-p (rx (eval input)) input) ;; More rx

如果你很清楚(正则表达式)语法字符的话, 可以很容易的看出,这个问题只是由引用或转义语法字符引起的。 函数 regexp-quote 可以转义这些字符,这很简单。 rx 默认转义,可以直接传入字符串。 最后,可通过 eval 语法来使用字符串变量,来完成转义。

2 Variables And Ranges

‘(any SET ...)’
‘(in SET ...)’
‘(char SET ...)’
     matches any character in SET ....  SET may be a character or string.
     Ranges of characters can be specified as ‘A-Z’ in strings.
     Ranges may also be specified as conses like ‘(?A . ?Z)’.

     SET may also be the name of a character class: ‘digit’,
     ‘control’, ‘hex-digit’, ‘blank’, ‘graph’, ‘print’, ‘alnum’,
     ‘alpha’, ‘ascii’, ‘nonascii’, ‘lower’, ‘punct’, ‘space’, ‘upper’,
     ‘word’, or one of their synonyms.

问题:创建一个正则表达式来匹配 calendar 的所有常见拼写错误,这样就可在文档中找到这个词, 从而不必来考验写作者的拼写能力。 允许在每个元音位置使用a或e。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
(s-matches-p (rx "c"
(any "a" "e")
"l"
(any "a" "e")
"nd"
(any "a" "e")
"r")

"celander")


(setq misspelling-pattern `(any "a" "e"))

(s-matches-p (rx "c"
(eval misspelling-pattern)
"l"
(eval misspelling-pattern)
"nd"
(eval misspelling-pattern)
"r")

"calendar")


"c[ae]l[ae]nd[ae]r" ;; Generated pattern

除了演示一个简单的范围构造,通过熟悉的 eval 使用子模式允许更加模块化地处理这些表达式,这有助于摆脱单一的连接字符串。

问题:创建一个正则表达式来匹配单个十六进制字符。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
(s-matches-p (rx (any "a-f" "A-F" "0-9"))
"A")

(s-matches-p (rx (in "a-f" "A-F" "0-9"))
"A") ;; Equivalently


"[0-9A-Fa-f]" ;; Generated pattern


(s-matches-p (rx (char hex-digit))
"d") ;; More rx

(s-matches-p (rx hex-digit)
"d") ;; Equivalently


"[[:xdigit:]]" ;; Generated pattern

最后,范围语法允许熟悉的破折号来表示字符范围。 Rather, the abstraction of special character ranges like [:upper:] or [:xdigit:] is nice to know. Other useful constructs such as word-start, line-end, and punctuation exist that is worthy to be explored.

3 Alternatives And Depth

‘(or SEXP1 SEXP2 ...)’
‘(| SEXP1 SEXP2 ...)’
     matches anything that matches SEXP1 or SEXP2, etc.  If all
     args are strings, use ‘regexp-opt’ to optimize the resulting
     regular expression.

‘(zero-or-one SEXP ...)’
‘(optional SEXP ...)’
‘(opt SEXP ...)’
     matches zero or one occurrences of A.

‘(and SEXP1 SEXP2 ...)’
‘(: SEXP1 SEXP2 ...)’
‘(seq SEXP1 SEXP2 ...)’
‘(sequence SEXP1 SEXP2 ...)’
     matches what SEXP1 matches, followed by what SEXP2 matches, etc.

‘(repeat N SEXP)’
‘(= N SEXP ...)’
     matches N occurrences.

问题:创建一个正则表达式,当重复应用于文本 Mary, Jane, and Sue went to Mary's house 会匹配 Mary, Jane, Sue 然后再次匹配 Mary 。

1
2
3
4
5
6
7
8
9
(s-match-strings-all
(rx (or "Mary" "Jane" "Sue"))
"Mary, Jane, and Sue went to Mary's house")


;; Output
'(("Mary") ("Jane") ("Sue") ("Mary"))

;; Generated pattern
"\\(?:Jane\\|Mary\\|Sue\\)"

这个简单的问题是使用与范围和类有关的交替构造的示例。 没有什么花哨的东西,但存在使其细微差别的可能性。

问题:创建一个匹配0到255的正则表达式。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
(setq range-expression ;; Expression and pattern separated for reuse
`(or "0"
(sequence "1" (optional digit (optional digit)))
(sequence "2" (optional
(or
(sequence (any "0-4") (optional digit))
(sequence "5" (optional (any "0-5")))
(sequence (any "6-9") (optional digit)))))
(sequence (any "3-9") (optional digit))))


(setq range-pattern (rx (eval range-expression)))

;; A test for the regular expression
(require 'cl)
(cl-every (lambda (number)
(s-matches-p range-pattern (number-to-string number)))

(number-sequence 0 255))


;; Generated pattern
"0\\|1\\(?:[[:digit:]][[:digit:]]?\\)?\\|2\\(?:[0-4][[:digit:]]?\\|5[0-5]?\\|[6-9][[:digit:]]?\\)?\\|[3-9][[:digit:]]?"

;; To use this IP Addresses
(setq ip4-pattern (rx (repeat 3 (sequence (eval range-expression) "."))
(eval range-expression)))


;; Testing for permutation might take too long, one is good enough
(s-matches-p ip4-pattern
"61.12.234.251")


;; Generated pattern
"\\(?:\\(?:0\\|1\\(?:[[:digit:]][[:digit:]]?\\)?\\|2\\(?:[0-4][[:digit:]]?\\|5[0-5]?\\|[6-9][[:digit:]]?\\)?\\|[3-9][[:digit:]]?\\)\\.\\)\\{3\\}\\(?:0\\|1\\(?:[[:digit:]][[:digit:]]?\\)?\\|2\\(?:[0-4][[:digit:]]?\\|5[0-5]?\\|[6-9][[:digit:]]?\\)?\\|[3-9][[:digit:]]?\\)"

上面的 range-expression 有问题,下面给出改正和测试如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
(setq range-expression ;; Expression and pattern separated for reuse
`(or "0"
(sequence "1" (optional digit (optional digit)))
(sequence "2" (optional
(or
(sequence (any "0-4") (optional digit))
(sequence "5" (optional (any "0-5")))
(optional digit))))
(sequence (any "3-9") (optional digit))))


(setq range-pattern (rx bol (eval range-expression) eol ))

;; A test for the regular expression
(require 'cl)
(cl-every (lambda (number)
(s-matches-p range-pattern (number-to-string number)))

(number-sequence 0 255))


(cl-every (lambda (number)
(not (s-matches-p range-pattern (number-to-string number))))

(number-sequence 256 355))

这个表达的想法是匹配第一个数字,然后考虑分支。 即使不深入解释,语法应该是有帮助的; 但三个新的结构值得好好说明下。 首先, optional 或 opt 语法与 zero-or-one 结构等价。 其次, sequence 或 seq 语法主要是一个表达式包装器,其中列表不是一个原子是必需的。 第三, repeat 语法与先前模式的重复构造相同。 不管新的语法如何,问题只是在展示语法。

另外,请记住为正则表达式编写测试。

在我忘记之前, eval 要求变量存在于解释器中; 这意味着,它们必须在使用之前通过 setq 进行全局设置。 这就是为什么在片段中的两个 setters 分别设置表达和模式的原因。 建议通过 defconst 或 defvar 设置表达式或模式作为重构。 不幸的是, let 不能与 eval 一起工作,但这不是一项巨大的成本。

4 Groups And Backreferencs

‘(submatch SEXP1 SEXP2 ...)’
‘(group SEXP1 SEXP2 ...)’
     like ‘and’, but makes the match accessible with ‘match-end’,
     ‘match-beginning’, and ‘match-string’.

‘(submatch-n N SEXP1 SEXP2 ...)’
‘(group-n N SEXP1 SEXP2 ...)’
     like ‘group’, but make it an explicitly-numbered group with
     group number N.

问题:创建一个正则表达式,以yyyy-mm-dd格式匹配任何日期,并分别捕获年,月和日。 作为额外的挑战,请将组命名。

1
2
3
4
5
6
7
8
9
10
11
12
13
(setq date-pattern
(rx (group-n 3 (repeat 4 digit))
"-"
(group-n 2 (repeat 2 digit))
"-"
(group-n 1 (repeat 2 digit))))


(s-match-strings-all date-pattern
(format-time-string "%F"))


;; Output and pattern, notice it is day, month and year or reverse order
"\\(?3:[[:digit:]]\\{4\\}\\)-\\(?2:[[:digit:]]\\{2\\}\\)-\\(?1:[[:digit:]]\\{2\\}\\)"
'(("2017-03-30" "30" "03" "2017"))

捕获 group 是本质的, 这是语法起作用的地方。 命名 group 在这里是不可能的,相反,仅限于编号 group 。 需要注意的,这不是宏的限制,而是 Emacs Lisp 正则表达式语法的限制。

group-n 或 group 语法在意图上很明显。 第一个参数代表组号,其余的是实际的表达式。 没有什么花哨。

问题:创建一个正则表达式,以yyyy-mm-dd格式匹配“神奇”日期。 如果年份减去世纪,月份和月份的日期都是相同的数字,则日期是神奇的。 例如,2008-08-08是一个神奇的约会。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
(setq magical-pattern
(rx
(repeat 2 digit)
(group-n 1 (repeat 2 digit))
"-"
(backref 1)
"-"
(backref 1)))


(s-matches-p magical-pattern
"2008-08-08")


;; Generated pattern
"[[:digit:]]\\{2\\}\\(?1:[[:digit:]]\\{2\\}\\)-\\1-\\1"

这只是显示反向引用可用。 backref 语法只是用数字参数调用组。 再一次,没什么复杂的。

5 re-builder

为了更好的检测编写的正则表达式, Emacs 中存在用于测试和试验正则表达式的用户界面: re-builder 。 在包含文本的缓冲区上执行命令 re-builder 或 regexp-builder ,然后执行 reb-change-syntax 并选择 rx 。 如下图所示。 exploring-emacs-rx--screencast.gif

这个UI可以处理原始表达式,但我们这里只对rx感兴趣。 详细说明,每次表达式更新时,它都会突出显示任何可能的匹配项。 虽然它不像动态或程序化,但它作为一个快速实验和检查很方便。

6 总结

rx 宏不能作为学习正则表达式的替代品,因为它构建的DSL不能完全覆盖所有的细节。但是写原始的正则表达式,真是很痛苦, 所以使用 rx 宏可在更高的抽象等级上来构造正则表达式,可在更清晰的语义下,构造正则表达式。 上面没有给出所有的正则语法构造,只给出一些常用的特征,有任何疑惑,请直接阅读函数文档。

Last Updated 2018-03-01 Thu 22:33.
Render by hexo-renderer-org with Emacs 25.3.2 (Org mode 8.2.10)

Go实现鼓励金发放逻辑

发表于 2018-01-26 | 分类于 技术积累 |

什么是鼓励金?我想大家应该都有用过,例如今早我买包子时,就抵扣了部分金额。 用支付宝或者微信支付,支付成功后会返还一小笔钱,从周日到周四累计5天,然后在周五和周六抵现金使用, 这笔钱就是鼓励金(当然支付宝称作奖励金)。 我们现在几乎每天都在使用支付宝或者微信,每天都会接触鼓励金,但是你知道鼓励金发放的一般逻辑嘛, 或者说如果让你来做一个类似鼓励金一样的产品,你会怎样来实现发放逻辑呢。

1 问题描述

问题描述,洋气一点,可以称作产品需求,需求如下:

  • 根据订单金额分阶段发放,金额越高,得到的鼓励金要相应升高
  • 每个金额阶段中再分层,每个层次指定发放金额的最小值和最大值,并指定百分比
  • 商家可以根据上述两条规则自定义自己的发放逻辑
  • 商家可分时段自定义发放倍率(放大或者缩小发送的金额)
  • 平台可自定义全平台的发放倍率

2 解决思路与数据结构设计

数据结构如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
type Ecrg_fee_dura struct {
Upper float64
Lower float64
}

type Ecrg_fee_item struct {
Num int
Dura *Ecgr_fee_dura
}

type Ecrg_fee struct {
Amount float64
Item_arr []*Ecgr_fee_item
}

Ecrg_fee_arr []*Ecrg_fee = []*Ecrg_fee{
&Ecrg_fee{
Amount: 99.99,
Item_arr: []*Ecrg_fee_item{
&Ecrg_fee_item{Num: 700, Dura: &Ecrg_fee_dura{Upper: 1.1, Lower: 0.8}},
&Ecrg_fee_item{Num: 900, Dura: &Ecrg_fee_dura{Upper: 2.0, Lower: 1.0}},
&Ecrg_fee_item{Num: 1000, Dura: &Ecrg_fee_dura{Upper: 5.0, Lower: 1.8}},
},
},
&Ecrg_fee{
Amount: 49.99,
Item_arr: []*Ecrg_fee_item{
&Ecrg_fee_item{Num: 700, Dura: &Ecrg_fee_dura{Upper: 0.6, Lower: 0.25}},
&Ecrg_fee_item{Num: 900, Dura: &Ecrg_fee_dura{Upper: 1.25, Lower: 0.5}},
&Ecrg_fee_item{Num: 1000, Dura: &Ecrg_fee_dura{Upper: 2.0, Lower: 1.0}},
},
},
&Ecrg_fee{
Amount: 29.99,
Item_arr: []*Ecrg_fee_item{
&Ecrg_fee_item{Num: 700, Dura: &Ecrg_fee_dura{Upper: 0.4, Lower: 0.25}},
&Ecrg_fee_item{Num: 900, Dura: &Ecrg_fee_dura{Upper: 0.6, Lower: 0.3}},
&Ecrg_fee_item{Num: 1000, Dura: &Ecrg_fee_dura{Upper: 1.0, Lower: 0.5}},
},
},
&Ecrg_fee{
Amount: 19.99,
Item_arr: []*Ecrg_fee_item{
&Ecrg_fee_item{Num: 700, Dura: &Ecrg_fee_dura{Upper: 0.25, Lower: 0.1}},
&Ecrg_fee_item{Num: 900, Dura: &Ecrg_fee_dura{Upper: 0.5, Lower: 0.2}},
&Ecrg_fee_item{Num: 1000, Dura: &Ecrg_fee_dura{Upper: 0.8, Lower: 0.4}},
},
},
}

给出数据结构和规则列表示例,应该就明白一半了,另一半的说明如下:

  • Ecrg_fee_arr 数组金额是从高到底,这里使用有序的列表来表示区间,第一项代表区间99.99到无限大,第二项代表49.99到99.99…
  • Ecrg_fee_item 定义了中奖规则,由一个整数 Num 和一个区间 Dura 组成, Dura 代表发放金额的上限和下限, Num 就要放到数组中来理解, 同样这里也使用了有序数组来表示区间,只不过这里使用的是递增数组。 Item_arr 的第一项表示1-700,代表的含义是随机1-1000,命中1-700的概率,也就是说这里使用此项定义出70%的概率区间; 第二项表示701-900,代表的含义是随机1-1000,命中701-900的概率,也就是说这里使用此项定义出20%的概率区间…
  • 数据结构和以上的解析基本映射出相应的算法执行步骤:
    1. 比对金额,定位金额区间
    2. 生成随机数,定位发放规则
    3. 生成随机数,生成鼓励金

3 编码实现

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
// 四舍五入
func FormatPrice(p float64) float64 {
p = math.Floor((p+0.005)*100) / 100
return math.Max(p, 0.01)
}

// 获取全平台倍率
func GetEcrgFactor() float64 {
return 1.0
}

// 获取鼓励金发放订单最低金额
func GetEcrgThreshold() float64 {
return 9.9
}

func CalcEcrgAmount(
amount float64, // 订单金额
factor float64, // 发放倍率
ecrg_fee_arr []*Ecrg_fee, // 发放规则
) (
ecrg_amount float64,
code int, err error,
) {
if amount < Ecrg_amount_threshold {
return
}

// 添加鼓励金发放倍率
factor = factor * GetEcrgFactor()

// 规则未定义
if len(ecrg_fee_arr) < 1 {
ecrg_amount = amount * 0.01 * factor
ecrg_amount = FormatPrice(ecrg_amount)
return
}

rand.Seed(time.Now().UnixNano())
// 遍历区间列表
for index, _ := range ecrg_fee_arr {
ecrg_fee := ecrg_fee_arr[index]

// 定位金额区间
if amount-ecrg_fee.Amount > 0.001 {
// 生成随机数--用于定位发放规则
rand_num := rand.Intn(1000) + 1
for index, _ := range ecrg_fee.Item_arr {
ecrg_item := ecrg_fee.Item_arr[index]
// 定位中奖区间
if rand_num <= ecrg_item.Num {
fee_dura := ecrg_item.Dura
// 生成随机数--用于生成发放金额
rand_n := rand.Intn(100) + 1
// 生成发放金额
ecrg_amount = fee_dura.Lower + ((float64(rand_n)/100.00)*
(fee_dura.Upper-fee_dura.Lower))*factor
log.Printf("[CalcEcrgAmount] amount: %v, factor %v, "+
"rand_num: %v, rand_n: %v, dura: %v, ecrg_amount: %v",
amount, factor, rand_num, rand_n, *fee_dura, ecrg_amount,
)

// 发放金额格式化
ecrg_amount = FormatPrice(ecrg_amount)
return
}
}
}
}

return
}

4 总结

以上给出了一个鼓励金或者奖励金一个粗糙的实现,欢迎大家,给出更好的设计方案,欢迎讨论。

Last Updated 2018-01-29 Mon 18:23.
Render by hexo-renderer-org with Emacs 25.3.2 (Org mode 8.2.10)

tmux自动化

发表于 2017-12-18 | 分类于 技术积累 |
1
2
3
4
#!/bin/bash

tmux new -s htop \; neww -d 'cd ~/ && htop' \; splitw -d \; selectp -t 1 \; detach
tmux new -s top \; neww -d 'cd ~/ && top' \; splitw -d \; selectp -t 1 \; detach
1
2
3
4
5
6
#!/bin/bash

tmux new -s htop \; \
send-keys -t htop:0 'cd ~/ && htop' C-m \; \
splitw -d \; selectp -t 1 \; \
send-keys -t htop:0.1 'cd ~/ && clear' C-m \; detach
1
2
3
4
5
6
7
8
9
10
11
12
#!/bin/bash

CMDS=( "htop" "top" )
CMDPATH="~"

for cmd in "${CMDS[@]}"
do
tmux new -s $cmd \; \
send-keys -t $cmd:0 'cd '$CMDPATH' && '$cmd C-m \; \
splitw -d \; selectp -t 1 \; \
send-keys -t $cmd:0.1 'cd '$CMDPATH' && clear' C-m \; detach
done
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
#!/bin/bash

servs = ("cashier" "notify" "magic" "privacy")
rootPath = $GOPATH/src/path-to-serv

for serv in "${servs[@]}"
do
tmux has-session -t $serv
if [ $? = 0]; then
continue
fi

servPath = $rootPath"/"$serv
tmux new -s $serv -n serv \; \
send-keys -t $serv:0 'cd '$servPath' && bee run' \; \
splitw -d \; selectp -t 1 \; \
send-keys -t $serv:0.1 'cd '$servPath C-m \; detach
done
Last Updated 2018-04-25 Wed 22:19.
Render by hexo-renderer-org with Emacs 25.3.2 (Org mode 8.2.10)

GDB-UI试用

发表于 2017-12-09 | 分类于 技术积累 |

1 源码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
typedef struct {
float a;
float b;
} substruct;

struct {
int i;
substruct r;
} c;

void main() {
int n = 4;
int m[10] = {0,1,4,9,16,25,36,49,64,81};
n = 5;
myproc(n);
c.i = 1;
c.r.a = 0.5;
c.r.b = 0.25;
}
1
2
3
4
5
6
void myproc(n)
{

int p;
p = 2*n;
printf("Two times %d is %d\n", n, p);
}

用 -g 选项编译程序:

1
2
cc -g -c myproc.c
cc -g -o myprog myprog.c myproc.o

2 使用

参见在Emacs中使用gdb调试程序。

Last Updated 2017-12-11 Mon 13:54.
Render by hexo-renderer-org with Emacs 25.3.2 (Org mode 8.2.10)

go-dlv试用

发表于 2017-12-09 | 分类于 技术积累 |

1 源码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
package main

import (
"fmt"
"sync"
"time"
)

func dostuff(wg *sync.WaitGroup, i int) {
fmt.Printf("goroutine id %d\n", i)
time.Sleep(300 * time.Second)
fmt.Printf("goroutine id %d\n", i)
wg.Done()
}

func main() {
var wg sync.WaitGroup
workers := 10

wg.Add(workers)
for i := 0; i < workers; i++ {
go dostuff(&wg, i)
}
wg.Wait()
}
Last Updated 2017-12-10 Sun 16:57.
Render by hexo-renderer-org with Emacs 25.3.2 (Org mode 8.2.10)
12…4
Brantou

Brantou

39 日志
5 分类
46 标签
RSS
GitHub Twitter E-Mail Jianshu
© 2017 — 2018 Brantou
由 Hexo 强力驱动
|
主题 — NexT.Pisces v5.1.3
Hosted by GitHub Pages