DAY 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 type MyQueue struct { in []int out []int } func Constructor () MyQueue { return MyQueue{ in: []int {}, out: []int {}, } } func (this *MyQueue) Push(x int ) { this.in = append (this.in, x) } func (this *MyQueue) shift() { for len (this.in) != 0 { this.out = append (this.out, this.in[len (this.in)-1 ]) this.in = this.in[:len (this.in)-1 ] } } func (this *MyQueue) Pop() int { if len (this.out) == 0 { this.shift() } ans := this.out[len (this.out)-1 ] this.out = this.out[:len (this.out)-1 ] return ans } func (this *MyQueue) Peek() int { if len (this.out) == 0 { this.shift() } return this.out[len (this.out)-1 ] } func (this *MyQueue) Empty() bool { return len (this.in) == 0 && len (this.out) == 0 }
一个队列就够了
出栈的话,把前 n-1
个元素扔到后面去(我称之为 shift
操作),当前元素就是刚入队的元素了
Top
的话就先出栈再放进去
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 type MyStack struct { q []int } func Constructor () MyStack { return MyStack{ q: []int {}, } } func (this *MyStack) Push(x int ) { this.q = append (this.q, x) } func (this *MyStack) shift() { n := len (this.q) for i := 0 ; i < n-1 ; i++ { this.q = append (this.q[1 :], this.q[0 ]) } } func (this *MyStack) Pop() int { this.shift() ans := this.q[0 ] this.q = this.q[1 :] return ans } func (this *MyStack) Top() int { ans := this.Pop() this.Push(ans) return ans } func (this *MyStack) Empty() bool { return len (this.q) == 0 }
也可以换个思路,在 Push
的时候就 shift
也行,看上去更简单
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 type MyStack struct { q []int } func Constructor () MyStack { return MyStack{ q: []int {}, } } func (this *MyStack) Push(x int ) { this.q = append (this.q, x) this.shift() } func (this *MyStack) shift() { n := len (this.q) for i := 0 ; i < n-1 ; i++ { this.q = append (this.q[1 :], this.q[0 ]) } } func (this *MyStack) Pop() int { ans := this.q[0 ] this.q = this.q[1 :] return ans } func (this *MyStack) Top() int { return this.q[0 ] } func (this *MyStack) Empty() bool { return len (this.q) == 0 }
DAY 11 经典的栈应用
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 isValid (s string ) bool { stack := []rune {} for _, c := range s { switch c { case '(' , '[' , '{' : stack = append (stack, c) case ')' : if len (stack) == 0 || stack[len (stack)-1 ] != '(' { return false } stack = stack[:len (stack)-1 ] case ']' : if len (stack) == 0 || stack[len (stack)-1 ] != '[' { return false } stack = stack[:len (stack)-1 ] case '}' : if len (stack) == 0 || stack[len (stack)-1 ] != '{' { return false } stack = stack[:len (stack)-1 ] } } if len (stack) != 0 { return false } return true }
1 2 3 4 5 6 7 8 9 10 11 12 13 func removeDuplicates (s string ) string { stack := []rune {} for _, c := range s { if len (stack) != 0 && c == stack[len (stack)-1 ] { stack = stack[:len (stack)-1 ] } else { stack = append (stack, c) } } return string (stack) }
经典中的经典
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 evalRPN (tokens []string ) int { stack := []int {} for _, s := range tokens { n := len (stack) switch s { case "+" : stack = append (stack[:n-2 ], stack[n-2 ]+stack[n-1 ]) case "-" : stack = append (stack[:n-2 ], stack[n-2 ]-stack[n-1 ]) case "*" : stack = append (stack[:n-2 ], stack[n-2 ]*stack[n-1 ]) case "/" : stack = append (stack[:n-2 ], stack[n-2 ]/stack[n-1 ]) default : stack = append (stack, atoi(s)) } } return stack[0 ] } func atoi (x string ) int { opt, ans := 1 , 0 for _, c := range x { if c == '-' { opt = -1 continue } ans = ans*10 + int (c-'0' ) } return ans * opt }
DAY 12 周日休息
DAY 13 非常好的单调队列例题
单调队列,队列中从头到尾单调递减
Pop:传入当前窗口移动需要弹出的值,如果等于头元素则弹出 Push:在尾部尝试加入,如果遇到比当前元素小的都从尾部弹出 GetMax:取头元素 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 type MonoQ struct { data []int } func NewMonoQ () MonoQ { return MonoQ{ data: []int {}, } } func (q *MonoQ) Pop(x int ) { if len (q.data) != 0 && x == q.data[0 ] { q.data = q.data[1 :] } } func (q *MonoQ) Push(x int ) { for len (q.data) != 0 && x > q.data[len (q.data)-1 ] { q.data = q.data[:len (q.data)-1 ] } q.data = append (q.data, x) } func (q *MonoQ) GetMax() int { return q.data[0 ] } func maxSlidingWindow (nums []int , k int ) []int { n := len (nums) ans := []int {} q := NewMonoQ() for i := 0 ; i < k; i++ { q.Push(nums[i]) } ans = append (ans, q.GetMax()) for i := k; i < n; i++ { q.Pop(nums[i-k]) q.Push(nums[i]) ans = append (ans, q.GetMax()) } return ans }
两种方法,拿到频率的 map 之后用堆维护前 K 个,或者直接排序再取前 K 个
复习一下 Golang 里面的优先队列和排序
用惯了 C++ STL 的开箱即用的优先队列,我只能说 Golang 的优先队列真的不好用(
言归正传,本体的两种方法
直接排序
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 func topKFrequent (nums []int , k int ) []int { m := make (map [int ]int ) for _, v := range nums { m[v]++ } count := make ([][2 ]int , 0 , len (m)) for k, v := range m { count = append (count, [2 ]int {k, v}) } sort.Slice(count, func (i, j int ) bool { return count[i][1 ] > count[j][1 ] }) ans := make ([]int , 0 , k) for i := 0 ; i < k; i++ { ans = append (ans, count[i][0 ]) } return ans }
还可以更简单
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 func topKFrequent (nums []int , k int ) []int { m := make (map [int ]int ) for _, v := range nums { m[v]++ } ans := make ([]int , 0 , len (m)) for k, _ := range m { ans = append (ans, k) } sort.Slice(ans, func (i, j int ) bool { return m[ans[i]] > m[ans[j]] }) return ans[:k] }
维护大顶堆
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 type Item struct { value int freq int } type PriorityQueue []Itemfunc (pq PriorityQueue) Len() int { return len (pq) }func (pq PriorityQueue) Less(i, j int ) bool { return pq[i].freq < pq[j].freq }func (pq PriorityQueue) Swap(i, j int ) { pq[i], pq[j] = pq[j], pq[i] }func (pq *PriorityQueue) Push(x interface {}) { item := x.(Item) *pq = append (*pq, item) } func (pq *PriorityQueue) Pop() interface {} { old := *pq n := len (old) item := old[n-1 ] *pq = old[0 : n-1 ] return item } func topKFrequent (nums []int , k int ) []int { m := make (map [int ]int ) for _, num := range nums { m[num]++ } pq := make (PriorityQueue, 0 ) for value, freq := range m { heap.Push(&pq, Item{value, freq}) if pq.Len() > k { heap.Pop(&pq) } } ans := make ([]int , k) for i := 0 ; i < k; i++ { item := heap.Pop(&pq).(Item) ans[i] = item.value } return ans }