算法
INFO
烦死了
摩尔投票法
用于找出一堆数字中出现频率大于一半的算法,即找出众数。
实现方式
遍历一次数组,记录两个值,一个是当前记录的数字和这个数字剩余的次数。
go
func majorityElement(nums []int) int {
var maxNum int
occurTime := 0
for _, v := range nums {
if v != maxNum {
if occurTime == 0 {
maxNum = v
occurTime++
} else {
occurTime--
}
} else {
occurTime++
}
}
return maxNum
}
复杂度
- 时间复杂度:O(n)
- 空间负责度:O(1)
双指针
经常用到,例如删除有序数组中的重复项,或者计算两数之和
删除有序数组中的重复项
go
func removeDuplicates(nums []int) int {
n := len(nums)
if n == 0 {
return 0
}
slow := 1
for fast := 1; fast < n; fast++ {
if nums[fast] != nums[fast-1] {
nums[slow] = nums[fast]
slow++
}
}
return slow
}
两数之和
寻找一个非递减数组中两数之和等于某特定数字的两数。 初始时两个指针分别指向第一个元素位置和最后一个元素的位置。每次计算两个指针指向的两个元素之和,并和目标值比较。如果两个元素之和等于目标值,则发现了唯一解。如果两个元素之和小于目标值,则将左侧指针右移一位。如果两个元素之和大于目标值,则将右侧指针左移一位。移动指针之后,重复上述操作,直到找到答案。
KMP算法
用来在一个主文本字符串中查找一个模式字符串的出现位置。大学数据结构中的经典算法,还是挺难的。
实现方式
对于模式字符串,要先算一个next数组。next数组就是一个前缀表(prefix table)。前缀表是用来回退的,它记录了模式串与主串(文本串)不匹配的时候,模式串应该从哪里开始重新匹配。 前缀表代表的意思是该字符串中最长相同前后缀的长度,前后缀都是从左往右读。例如:aabaaf对应的前缀表就是010120
go
func computePrefix(pattern string) []int {
prefix := make([]int, len(pattern))
j := 0
for i := 1; i < len(pattern); {
if pattern[i] == pattern[j] {
j++
prefix[i] = j
i++
} else {
if j != 0 {
j = prefix[j-1]
} else {
prefix[i] = 0
i++
}
}
}
return prefix
}
复杂度
- 时间复杂度:O(m+n)