1.栈和队列理论基础
栈和队列的原理大家应该很熟悉了,队列是先进先出,栈是先进后出。
2.用栈实现队列
type MyQueue struct {
head []int
headSize int
store []int
storeSize int
}
func Constructor() MyQueue {
return MyQueue{
head : make([]int,100),
headSize : 0,
store : make([]int,100),
storeSize : 0,
}
}
func (this *MyQueue) Push(x int) {
this.store[this.storeSize] = x
this.storeSize++
}
func (this *MyQueue) Pop() int {
if this.headSize==0{
//需要将store中的数倒过来
for i:=this.storeSize;i>0;{
i--
this.head[this.headSize]=this.store[i]
this.headSize++
}
this.storeSize = 0
}
if this.headSize>0{
this.headSize--
return this.head[this.headSize]
}
return -1
}
func (this *MyQueue) Peek() int {
if this.headSize==0{
//需要将store中的数倒过来
for i:=this.storeSize;i>0;{
i--
this.head[this.headSize]=this.store[i]
this.headSize++
}
this.storeSize = 0
}
if this.headSize>0{
return this.head[this.headSize-1]
}
return -1
}
func (this *MyQueue) Empty() bool {
return this.headSize==0&&this.storeSize==0
}
3.用队列实现栈
type MyStack struct {
store []int
size int
}
func remove(s []int, i int) []int {
s[i] = s[len(s)-1]
return s[:len(s)-1]
}
func Constructor() MyStack {
return MyStack{make([]int,100),0}
}
func (this *MyStack) Push(x int) {
this.store[this.size]=x
this.size++
}
func (this *MyStack) Pop() int {
this.size--
return this.store[this.size]
}
func (this *MyStack) Top() int {
return this.store[this.size-1]
}
func (this *MyStack) Empty() bool {
return this.size==0
}
4.有效的括号
func isValid(s string) bool {
stack := Stack{}
for i := 0; i < len(s); i++ {
println(s[i])
if s[i] == 40 || s[i] == 91 || s[i] == 123 {
stack.Push(int(s[i]))
} else {
char, err := stack.Top()
if err != nil {
return false
}
if char == 40 && s[i] == 41 {
stack.Pop()
continue
}
if char == 91 && s[i] == 93 {
stack.Pop()
continue
}
if char == 123 && s[i] == 125 {
stack.Pop()
continue
}
return false
}
}
if stack.Len() != 0 {
return false
}
return true
}
type Stack []int
func (stack Stack) Len() int {
return len(stack)
}
func (stack Stack) IsEmpty() bool {
return len(stack) == 0
}
func (stack Stack) Cap() int {
return cap(stack)
}
func (stack *Stack) Push(value int) {
*stack = append(*stack, value)
}
func (stack Stack) Top() (int, error) {
if len(stack) == 0 {
return -1, errors.New("Out of index, len is 0")
}
return stack[len(stack)-1], nil
}
func (stack *Stack) Pop() (int, error) {
theStack := *stack
if len(theStack) == 0 {
return -1, errors.New("Out of index, len is 0")
}
value := theStack[len(theStack)-1]
*stack = theStack[:len(theStack)-1]
return value, nil
}
5.删除字符串中的所有相邻重复项
func removeDuplicates(s string) string {
chars := []byte(s)
p1 := 0
for i := 0; i < len(chars); i++ {
if(p1>0 && chars[p1-1]==chars[i]){
p1--
}else{
chars[p1] = chars[i]
p1++
}
}
return string(chars[:p1])
}
6.逆波兰表达式求值
func evalRPN(tokens []string) int {
numIndex := -1
numArr := make([]int,10000)
for _,str := range(tokens){
num, err := strconv.Atoi(str)
if err==nil{
//说明是数字
numIndex++
numArr[numIndex]=num
}else{
//说明是一个+-*/中的一种
num1 := numArr[numIndex]
numIndex--
num2 := numArr[numIndex]
switch str{
case "+":
numArr[numIndex]=num1+num2
case "-":
numArr[numIndex]=num2-num1
case "*":
numArr[numIndex]=num1*num2
case "/":
numArr[numIndex]=num2/num1
}
}
}
return numArr[0]
}
7.滑动窗口最大值
这道题目需要使用单调队列
// 封装单调队列的方式解题
// 那么这个维护元素单调递减的队列就叫做单调队列
// 即单调递减或单调递增的队列
type MyQueue struct {
queue []int
}
func NewMyQueue() *MyQueue {
return &MyQueue{
queue: make([]int, 0),
}
}
func (m *MyQueue) Front() int {
return m.queue[0]
}
func (m *MyQueue) Back() int {
return m.queue[len(m.queue)-1]
}
func (m *MyQueue) Empty() bool {
return len(m.queue) == 0
}
// push(value):如果push的元素value大于入口元素的数值,那么就将队列入口的元素弹出,直到push元素的数值小于等于队列入口元素的数值为止
func (m *MyQueue) Push(val int) {
for !m.Empty() && val > m.Back() {
m.queue = m.queue[:len(m.queue)-1]
}
m.queue = append(m.queue, val)
}
// pop(value):如果窗口移除的元素value等于单调队列的出口元素,那么队列弹出元素,否则不用任何操作
func (m *MyQueue) Pop(val int) {
if !m.Empty() && val == m.Front() {
m.queue = m.queue[1:]
}
}
func maxSlidingWindow(nums []int, k int) []int {
queue := NewMyQueue()
length := len(nums)
res := make([]int, 0)
// 先将前k个元素放入队列
for i := 0; i < k; i++ {
queue.Push(nums[i])
}
// 记录前k个元素的最大值
res = append(res, queue.Front())
for i := k; i < length; i++ {
// 滑动窗口移除最前面的元素
queue.Pop(nums[i-k])
// 滑动窗口添加最后面的元素
queue.Push(nums[i])
// 记录最大值
res = append(res, queue.Front())
}
return res
}
8.前K个高频元素
这题目需要实现go中提供的heap的接口。使用大顶堆即可完成任务。
func topKFrequent(nums []int, k int) []int {
items := make(map[int]*Item, 0)
for i := 0; i < len(nums); i++ {
item, ok := items[nums[i]]
if !ok {
items[nums[i]] = &Item{key: nums[i], value: 1}
} else {
item.value++
}
}
hp := &ItemHeap{}
heap.Init(hp)
for _, value := range items {
heap.Push(hp, *value)
}
res := make([]int, k)
for i := 0; i < k; i++ {
item := heap.Pop(hp)
res[i] = item.(Item).key
}
return res
}
//大顶堆
type Item struct {
// 排序的关键词
key int
// value,用来记录出现的次数
value int
}
type ItemHeap []Item
func (h ItemHeap) Len() int {
return len(h)
}
func (h ItemHeap) Swap(i, j int) {
h[i], h[j] = h[j], h[i]
}
func (h ItemHeap) Less(i, j int) bool {
return h[i].value > h[j].value
}
// 实现heap.Interface接口定义的额外方法
func (h *ItemHeap) Push(item interface{}) {
*h = append(*h, item.(Item))
}
// 这个方法不是给用户使用的
func (h *ItemHeap) Pop() interface{} {
old := *h
n := len(old)
x := old[n-1]
*h = old[0 : n-1]
return x
}