剑指 Offer II(专项突击版) 解题记录 golang版 第11-15天 033-046

记录了初步解题思路 以及本地实现代码;并不一定为最优 也希望大家能一起探讨 一起进步




第 11 天 哈希表

033. 变位词组

将字符串内字符从小到大排序 变成一个tag tag相同的说明字符串内字符出现情况相同

func groupAnagrams(strs []string) [][]string {
	var m = make(map[string][]string)
	for _, str := range strs {
		s := []byte(str)
		sort.Slice(s, func(i, j int) bool { return s[i] < s[j] })
		tag := string(s)
		m[tag] = append(m[tag], str)
	}
	var ans [][]string
	for _, v := range m {
		ans = append(ans, v)
	}
	return ans

}

034. 外星语言是否排序

map记录每个字母新的顺序

func isAlienSorted(words []string, order string) bool {
	var m = make(map[string]int)

	for i, c := range order {
		m[string(c)] = i
	}

	for i := 0; i < len(words)-1; i++ {
		var w1, w2 = words[i], words[i+1]
		var l1, l2 = len(w1), len(w2)
		var minl int
		if l1 < l2 {
			minl = l1
		} else {
			minl = l2
		}
		var same = true
		for loc := 0; loc < minl; loc++ {
			var c1 = string(w1[loc])
			var c2 = string(w2[loc])
			if m[c1] > m[c2] {
				return false
			} else if m[c1] < m[c2] {
				same = false
				break
			} else {
				continue
			}
		}
		if l1 > minl && same {
			return false
		}
	}
	return true
}

035. 最小时间差

将所有时间点转化为分钟 0-1440
排序后比较相邻的时间差 最后比较开头和结尾

func findMinDifference(timePoints []string) int {
	if len(timePoints) > 24*60 {
		return 0
	}

	var l []int
	for _, tp := range timePoints {
		l = append(l, timeToInt(tp))
	}
	sort.Ints(l)
	var ans = 1440 + l[0] - l[len(l)-1]
	for i := 0; i < len(l)-1; i++ {
		ans = min(ans, l[i+1]-l[i])
	}
	return ans

}

func min(i, j int) int {
	if i < j {
		return i
	}
	return j
}

func timeToInt(s string) int {
	r := []rune(s)
	ans := (int(r[0]-'0')*10+int(r[1]-'0'))*60 + int(r[3]-'0')*10 + int(r[4]-'0')
	return ans
}


第 12 天 栈

036. 后缀表达式

遇到数字压入栈中
遇到运算符 取栈顶两个数字计算
将结果压入栈中

func evalRPN(tokens []string) int {
	var l []int
	for _, c := range tokens {
		v, err := strconv.Atoi(c)
		if err != nil {
			var n = len(l) - 1
			var v1, v2 = l[n-1], l[n]
			l = l[:n-1]
			switch c {
			case "+":
				l = append(l, v1+v2)
			case "-":
				l = append(l, v1-v2)
			case "*":
				l = append(l, v1*v2)
			case "/":
				l = append(l, v1/v2)
			}
		} else {
			l = append(l, v)
		}
	}
	return l[0]
}

037. 小行星碰撞

ans用来记录当前状态
如果ans为空或者行星为正 则直接加入ans中
如果行星为负 且前一个也为负 则永远不会消失 加入ans
只有当前一个为正 当前为负是会发生相撞
如果当前为负 将前面所有小于目前行星大小且运动方向为右的都去除 记录位置loc
如果位置loc>=0 说明ans中还有行星
如果ans中最后一个行星与当前大小相同方向相反 则两个都消失
若ans最后一个为证 则当前行星消失 记录ans = ans[0:loc]
否则当前行星存在 ans = append(ans, cur)

func asteroidCollision(asteroids []int) []int {
	var ans []int
	for _, cur := range asteroids {
		if len(ans) == 0 || cur > 0 {
			ans = append(ans, cur)
			continue
		}
		pre := ans[len(ans)-1]
		if pre < 0 {
			ans = append(ans, cur)
			continue
		}
		var loc = len(ans) - 1
		for loc >= 0 && ans[loc] > 0 && ans[loc]+cur < 0 {
			loc -= 1
		}
		if loc >= 0 {
			if ans[loc]+cur == 0 {
				ans = ans[:loc]
			} else {
				ans = ans[:loc+1]
				if ans[loc] < 0 {
					ans = append(ans, cur)
				}
			}

		} else if loc == -1 {
			ans = []int{cur}
		}
	}
	return ans

}

038. 每日温度

单调栈
如果栈为空 或者栈顶温度比当前高 则将当前位置入栈
将所有比当前温度低的栈顶元素弹出 更新这些位置的值

func dailyTemperatures(temperatures []int) []int {
	var n = len(temperatures)
	var ans = make([]int, n)
	var stack []int
	for i, temp := range temperatures {
		var n = len(stack)
		if n == 0 || temperatures[stack[n-1]] >= temp {
			stack = append(stack, i)
		} else {
			var loc = n - 1
			for loc >= 0 && temperatures[stack[loc]] < temp {
				ans[stack[loc]] = i - stack[loc]
				loc -= 1
			}
			stack = stack[:loc+1]
			stack = append(stack, i)
		}
	}
	return ans

}

第 13 天 栈

039. 直方图最大矩形面积

单调栈 stack用来存放位置i
栈为空 或者当前位置值比栈顶位置值大时 入栈
如果当前值比较小 将栈顶值弹出
计算栈顶值能够围成的面积
h为栈顶值的高度 h=heights[stack[-1]]
w为栈顶值能够围成的宽度
如果此时栈顶值是唯一的值 那么w = i
否则w为当前坐标-栈顶第二个的坐标-1 w = i-stack[-2]-1
area = w*h

func largestRectangleArea(heights []int) int {
	heights = append(heights, 0)
	var ans int
	var stack []int
	for i, height := range heights {
		var n = len(stack)
		if n == 0 || heights[stack[n-1]] < height {
			stack = append(stack, i)
			continue
		}
		var loc = n - 1
		for loc >= 0 && heights[stack[loc]] >= height {
			var h = heights[stack[loc]]
			var w int
			if loc == 0 {
				w = i
			} else {
				w = i - stack[loc-1] - 1
			}
			var area = h * w
			ans = max(ans, area)
			loc -= 1
		}
		stack = stack[:loc+1]
		stack = append(stack, i)
	}
	return ans
}

func max(i, j int) int {
	if i > j {
		return i
	}
	return j
}

040. 矩阵中最大的矩形

从第一行开始遍历
在第i行 压缩前i行为一行 从底部网上连续的1累加可以看成高度
转换为第39题 求最大矩形面积

func maximalRectangle(matrix [][]byte) int {
	if len(matrix) == 0 || len(matrix[0]) == 0 {
		return 0
	}
	var ans = 0
	var n, m = len(matrix), len(matrix[0])
	for i := 0; i < n; i++ {
		var curr = make([]int, m)
		for j := i; j < n; j++ {
			for k := 0; k < m; k++ {
				if i == j {
					if matrix[i][k] == '1' {
						curr[k] = 1
					}
				} else {
					if matrix[j][k] == '1' {
						curr[k] += 1
					} else {
						curr[k] = 0
					}
				}
			}
			ans = max(ans, largestRectangleArea(curr))
		}
	}
	return ans
}

func largestRectangleArea(heights []int) int {
	heights = append(heights, 0)
	var ans int
	var stack []int
	for i, height := range heights {
		var n = len(stack)
		if n == 0 || heights[stack[n-1]] < height {
			stack = append(stack, i)
			continue
		}
		var loc = n - 1
		for loc >= 0 && heights[stack[loc]] >= height {
			var h = heights[stack[loc]]
			var w int
			if loc == 0 {
				w = i
			} else {
				w = i - stack[loc-1] - 1
			}
			var area = h * w
			ans = max(ans, area)
			loc -= 1
		}
		stack = stack[:loc+1]
		stack = append(stack, i)
	}
	return ans
}

func max(i, j int) int {
	if i > j {
		return i
	}
	return j
}


第 14 天 队列

041. 滑动窗口的平均值

链表连接模拟滑动窗口
记录头尾
添加在尾部 并将头部往后移动

type Node struct {
	Next *Node
	Val  int
}

type MovingAverage struct {
	Size  int
	Count int
	Sum   int
	Head  *Node
	Tail  *Node
	Init  bool
}

/** Initialize your data structure here. */
func Constructor(size int) MovingAverage {
	var mv MovingAverage
	mv.Size = size
	mv.Head = new(Node)
	mv.Tail = mv.Head
	return mv
}

func (this *MovingAverage) Next(val int) float64 {
	var newNode = new(Node)
	newNode.Val = val
	this.Sum += val
	this.Tail.Next = newNode
	this.Tail = newNode
	if !this.Init {
		this.Init = true
		this.Head = this.Tail
	}
	if this.Count < this.Size {
		this.Count += 1
	} else {
		var next = this.Head.Next
		this.Sum -= this.Head.Val
		this.Head.Next = nil
		this.Head = next
	}
	return float64(this.Sum) / float64(this.Count)

}


042. 最近请求次数

链表双指针
在结尾添加新数
从开头去除已经过期的数
记录总数

type Node struct {
	Val  int
	Next *Node
}
type RecentCounter struct {
	Head  *Node
	Tail  *Node
	Count int
	Init  bool
}

func Constructor() RecentCounter {
	var rc RecentCounter
	rc.Head = new(Node)
	rc.Tail = rc.Head
	return rc
}

func (this *RecentCounter) Ping(t int) int {
	var node = new(Node)
	node.Val = t
	this.Tail.Next = node
	this.Tail = node
	this.Count += 1
	if !this.Init {
		this.Head = this.Tail
		this.Init = true
	}

	for this.Head.Val < t-3000 {
		var next = this.Head.Next
		this.Head.Next = nil
		this.Head = next
		this.Count -= 1
	}
	return this.Count
}

043. 往完全二叉树添加节点

BFS按层遍历
curr 储存当前层节点
next存储下一层节点

type CBTInserter struct {
	Root *TreeNode
	Curr []*TreeNode
	Next []*TreeNode
}

func Constructor(root *TreeNode) CBTInserter {
	var cbt CBTInserter
	cbt.Root = root
	curr := []*TreeNode{root}
	for {
		next := []*TreeNode{}
		var loc = -1
		for i, node := range curr {
			if node.Left != nil {
				next = append(next, node.Left)
			} else {
				loc = i
				break
			}
			if node.Right != nil {
				next = append(next, node.Right)
			} else {
				loc = i
				break
			}
		}
		//当前层满了
		if loc == -1 {
			curr = next[:]
			continue
		} else {
			cbt.Curr = curr[loc:]
			cbt.Next = next[:]
			break
		}

	}

	return cbt

}

func (this *CBTInserter) Insert(val int) int {
	var node = new(TreeNode)
	node.Val = val
	tmp := this.Curr[0]
	if tmp.Left == nil {
		tmp.Left = node
		this.Next = append(this.Next, node)
	} else if tmp.Right == nil {
		tmp.Right = node
		this.Next = append(this.Next, node)
		if len(this.Curr) == 1 {
			this.Curr = this.Next[:]
			this.Next = []*TreeNode{}
		} else {
			this.Curr = this.Curr[1:]
		}
	}
	return tmp.Val

}

func (this *CBTInserter) Get_root() *TreeNode {
	return this.Root
}

第 15 天 队列

044. 二叉树每层的最大值

BFS按层遍历
curr 储存当前层节点
next存储下一层节点

func largestValues(root *TreeNode) []int {
	if root == nil {
		return []int{}
	}
	var curr = []*TreeNode{root}
	var ans []int

	for len(curr) > 0 {
		var value = curr[0].Val
		var next []*TreeNode
		for _, node := range curr {
			value = max(value, node.Val)
			if node.Left != nil {
				next = append(next, node.Left)
			}
			if node.Right != nil {
				next = append(next, node.Right)
			}
		}
		ans = append(ans, value)
		curr = next[:]
	}
	return ans

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


045. 二叉树最底层最左边的值

BFS按层遍历
curr存储从左到右当前层节点
next存储下一层节点
如果next为空
那么当前层为最后一层 返回curr中第一个节点值

func findBottomLeftValue(root *TreeNode) int {

	var curr = []*TreeNode{root}

	for {
		var next []*TreeNode
		for _, node := range curr {
			if node.Left != nil {
				next = append(next, node.Left)
			}
			if node.Right != nil {
				next = append(next, node.Right)
			}
		}
		if len(next) == 0 {
			return curr[0].Val
		}
		curr = next[:]
	}
}

046. 二叉树的右侧视图

BFS按层遍历
curr存储从左到右当前层节点
next存储下一层节点
每一层保存最后一个节点

func rightSideView(root *TreeNode) []int {
	if root == nil {
		return []int{}
	}
	var curr = []*TreeNode{root}
	var ans []int

	for len(curr) > 0 {
		var next []*TreeNode
		for _, node := range curr {
			if node.Left != nil {
				next = append(next, node.Left)
			}
			if node.Right != nil {
				next = append(next, node.Right)
			}
		}
		ans = append(ans, curr[len(curr)-1].Val)
		curr = next[:]
	}
	return ans
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值