Skip to content

Commit

Permalink
最长公共子串序列
Browse files Browse the repository at this point in the history
  • Loading branch information
yezihack committed Dec 7, 2019
1 parent 1a9dfc0 commit a673775
Show file tree
Hide file tree
Showing 9 changed files with 244 additions and 8 deletions.
1 change: 1 addition & 0 deletions 16.排序算法/02.希尔排序.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package _6_排序算法
//希尔排序也是一种插入排序,是插入排序的改进版本
//希尔排序按增量分组.
//希尔排序不是稳定的排序
//速度: O(n^1.25)
func ShellSort(arr []int) {
for gap := len(arr)/2; gap>0; gap /= 2 {//增量分组
for i := gap; i < len(arr); i ++ { //插入排序
Expand Down
14 changes: 6 additions & 8 deletions 16.排序算法/sort_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ import (
"fmt"
"github.com/yezihack/algo/00.src"
"github.com/yezihack/algo/16.排序算法/exercise"
"sort"
"testing"
)

Expand Down Expand Up @@ -107,7 +106,7 @@ func TestBubble(t *testing.T) {
Bubble(arr)
fmt.Println(arr)
}

//冒泡排序
func TestBubbleSort(t *testing.T) {
arr := []int{8, 2, 1, 7, 4, 3, 5, 6}
arr = []int{1,2,3,4,5,6,7,8}
Expand Down Expand Up @@ -191,8 +190,6 @@ func TestQuickSort3(t *testing.T) {
}
//简单选择排序 不稳定排序,O(N^2)
func TestSimplySelectSort(t *testing.T) {
fmt.Println(1<<1, 1<<2, 1<<3, 1<<4, 1<<5, 1<<6)
fmt.Println(100>>1, 100>>2, 100>>3, 100>>4, 100>>5, 100>>6)
arr := []int{5, 2, 8, 7, 4, 3, 1, 6}
fmt.Println("before", arr)
SimplySelectSort(arr)
Expand All @@ -207,30 +204,31 @@ func TestSimplySelectSort(t *testing.T) {
t.Errorf("expect:%d, actual:%d\n", 4, arr[3])
}
}

//选择排序
func TestSelectSort(t *testing.T) {
arr := []int{3, 1, 4, 2}
SelectSort(arr)
src.Asset(1, t, 2, arr[1])
src.Asset(2, t, 4, arr[3])
src.Asset(3, t, 1, arr[0])
}

//归并排序
func TestMergeSort(t *testing.T) {
fmt.Println(MergeSort([]int{8, 2, 7, 6, 3, 2, 1, 5}))
fmt.Println(MergeSort([]int{3, 5, 2, 1, 4}))
}
//归并
func TestMergeSort2(t *testing.T) {
fmt.Println(exercise.MergeSort([]int{8, 2, 7, 6, 3, 2, 1, 5}))
fmt.Println(exercise.MergeSort([]int{3, 5, 2, 1, 4}))
}
//快排
func TestQuickSort2(t *testing.T) {
arr := []int{8, 3, 2, 5, 4, 1, 7, 6}
exercise.QuickSort(arr)
fmt.Println(arr)
sort.Ints()
}

//桶排序
func TestBucketSort(t *testing.T) {
arr := []int{8, 3, 2, 5, 4, 1, 7, 6, 3}
BucketSort(arr)
Expand Down
59 changes: 59 additions & 0 deletions 22.深度优先搜索/01.八皇后.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
package _2_深度优先搜索

import "fmt"

var result8 []int
var count = 8

func init() {
result8 = make([]int, count)
}


func Cal8Queens(row int) {
if row >= count {
printQueens(result8)
return
}
for column := 0; column < count; column ++ {
if isOk(row, column) {
result8[row] = column
Cal8Queens(row + 1)
}
}
}
func isOk(row, column int) bool {//判断row行column列放置是否合适
leftUp, rightUp := column + 1, column + 1
for i := row-1; i >= 0;i -- {
if result8[i] == column {
return false
}
if leftUp >= 0 {
if result8[i] == leftUp {
return false
}
}
if rightUp < 8 {
if result8[i] == rightUp {
return false
}
}
leftUp--
rightUp++
}
return true
}
//打印8*8矩阵
func printQueens(result []int) {
for row := 0; row < count; row ++ {
for column := 0; column < count; column ++ {
if result[row] == column {
fmt.Print("Q ")
} else {
fmt.Print("* ")
}
}
fmt.Println()
}
fmt.Println()
}
7 changes: 7 additions & 0 deletions 22.深度优先搜索/test_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package _2_深度优先搜索

import "testing"

func TestCal8Queens(t *testing.T) {
Cal8Queens(1)
}
68 changes: 68 additions & 0 deletions 23.动态规划/01.时间安排问题.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
package _3_动态规划

//题目参考: https://www.bilibili.com/video/av16544031
//抽象时间安排
type TaskEntry struct {
taskId int //任务ID
startTime int //开始时间
endTime int//结束时间
value int //价值
}
//任务之前可以执行的任务的抽象结构
type prevEntry struct {
taskId int //自身的任务ID
prevTaskId int//时间不冲突的任务ID,取最近的
}
//任务列表
var TaskList []*TaskEntry
var PrevList []*prevEntry

//初始数据
func init() {
TaskList = getTasks()
PrevList = GetPrev()
}
func getTasks() []*TaskEntry {
TaskList = make([]*TaskEntry, 8)
TaskList[0] = &TaskEntry{1,1, 4, 5}
TaskList[1] = &TaskEntry{2,3, 5, 1}
TaskList[2] = &TaskEntry{3,0, 6, 8}
TaskList[3] = &TaskEntry{4, 4, 7, 4}
TaskList[4] = &TaskEntry{5, 3, 8, 6}
TaskList[5] = &TaskEntry{6, 5, 9, 3}
TaskList[6] = &TaskEntry{7, 6, 10, 2}
TaskList[7] = &TaskEntry{8, 8, 11, 4}
return TaskList
}
//对任务的选择有两种, 选与不选.如何选则本身+前面prev可以做的任务. 如果不选则下一个任务
func GetPrev() []*prevEntry {
size := len(TaskList)
prev := make([]*prevEntry, size)
for i := 0; i < size; i ++ {
prev[i] = &prevEntry{taskId:TaskList[i].taskId}
startTime := TaskList[i].startTime
for j := i-1; j >= 0; j -- {
if startTime >= TaskList[j].endTime {
prev[i] = &prevEntry{TaskList[i].taskId, TaskList[j].taskId}
break
}
}
}
return prev
}
//求最优解OPT
func OPT(taskId int) int {
if taskId == 0 {
return 0
}
return max(OPT(taskId-1), TaskList[taskId-1].value + OPT(PrevList[taskId].taskId))
}
func max(x, y int) int {
if x > y {
return x
}
return y
}



14 changes: 14 additions & 0 deletions 23.动态规划/01.时间安排问题_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
package _3_动态规划

import (
"fmt"
"testing"
)

func TestGetPrev(t *testing.T) {
//打印做某任务还可以做前面的任务一种映射关系, 不过只取最近的一个可以做的任务
prev := GetPrev()
for _, item := range prev {
fmt.Printf("taskId:%d, prevId:%d\n", item.taskId, item.prevTaskId)
}
}
73 changes: 73 additions & 0 deletions 23.动态规划/02.最长公共子串.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
package _3_动态规划

import "fmt"

//计算fish和fosh的最长公共子串序列
//先抽象成数据模型. 利用矩阵查找关系
//思路: 先目标字符串抽象成字符行, 匹配字符串抽象成字符列. 行与列就成了矩阵
// 若row为行, col为列,比较之间的关系.
// 如果相等则选择左上方单元格的值加1
// 如果不相等则选择左边相邻和上方单元格中较大的那个值.
func PubStr(a, b string) string {
rChar := []byte(a)
cChar := []byte(b)
iRow, jCol := len(rChar), len(cChar)
var matrix [][]int //申请一个i行j列的矩阵
matrix = make([][]int, iRow)
for row := 0; row < iRow; row ++ {
matrix[row] = make([]int, jCol)
for col := 0; col < jCol; col ++ {
if row == 0 && col == 0 {//第一个单元格,特殊处理
if rChar[row] == cChar[col] {//如果两者相等则赋值1
matrix[row][col] = 1
} else {//如果不相等则赋值0
matrix[row][col] = 0
}
} else if rChar[row] == cChar[col] {//i行j列相等时则左上方单格的值加1.
matrix[row][col] = matrix[row-1][col-1] + 1
} else {//i行j列不相等时,则选择上方和左方邻居中较大的那个.
if row == 0 {
matrix[row][col] = matrix[row][col-1]
} else if col == 0 {
matrix[row][col] = matrix[row-1][col]
} else {
matrix[row][col] = max(matrix[row][col-1], matrix[row-1][col])
}
}
}
}
pArr := make([]byte, 0)//存储公共字符
count := 0
for _, rows := range matrix {
for key, val := range rows {
if val > count {
count = val
pArr = append(pArr, cChar[key])
}
}
}
//获取矩阵里最大的值.
printMatrix(rChar, cChar, matrix)
fmt.Printf("%s与%s的公共字符串:%c\n", a, b, pArr)
return string(pArr)
}
//打印矩阵,显示子串的关系
func printMatrix(rowChar, colChar []byte, mtr [][]int) {
for r, rows := range mtr {
if r == 0 {
fmt.Print(" ")
for _, rc := range colChar {
fmt.Print(string(rc), " ")
}
fmt.Println()
}
for c, col := range rows {
if c == 0 {
fmt.Printf("%c ", rowChar[r])
}
fmt.Printf("%d ", col)
}
fmt.Println()
}
fmt.Println()
}
13 changes: 13 additions & 0 deletions 23.动态规划/02.最长公共子串_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
package _3_动态规划

import (
"github.com/yezihack/algo/00.src"
"testing"
)

func TestPubStr(t *testing.T) {
src.Asset(1, t, "lue", PubStr("clues","blue"))
src.Asset(2, t, "fsh", PubStr("fish","fosh"))
src.Asset(3, t, "llo", PubStr("hello","kallo"))
src.Asset(4, t, "ks", PubStr("kiss","kas"))
}
3 changes: 3 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,9 @@
## 贪心思想
1. [非负整数a,删除k个元素,求最大值](21.贪心思想/01.求最大值.go)

## 动态规划
1 [最长公共子串序列](23.动态规划/02.最长公共子串.go)

## 各种算法已代码实现
1. 极客时间算法: https://github.com/wangzheng0822/algo

Expand Down

0 comments on commit a673775

Please sign in to comment.