剑指 Offer
本文是《剑指Offer》 的题解。
剑指 Offer 03. 数组中重复的数字
func findRepeatNumber(nums []int) int {
for i := 0; i < len(nums); i++ {
for nums[i] != i {
if nums[nums[i]] == nums[i] {
return nums[i]
}
nums[i], nums[nums[i]] = nums[nums[i]], nums[i]
}
}
return -1
}
剑指 Offer 04. 二维数组中的查找
func findNumberIn2DArray(matrix [][]int, target int) bool {
if len(matrix) == 0 || len(matrix[0]) == 0 {
return false
}
n, m := len(matrix), len(matrix[0])
i, j := 0, m-1
for i < n && j >= 0 {
if matrix[i][j] == target {
return true
} else if matrix[i][j] < target {
i++
} else {
j--
}
}
return false
}
剑指 Offer 05. 替换空格
func replaceSpace(s string) string {
var sb strings.Builder
for _, ch := range s {
if ch != ' ' {
sb.WriteRune(ch)
} else {
sb.WriteString("%20")
}
}
return sb.String()
}
剑指 Offer 06. 从尾到头打印链表
/**
* Definition for singly-linked list.
* type ListNode struct {
* Val int
* Next *ListNode
* }
*/
func reversePrint(head *ListNode) []int {
res := []int{}
if head == nil {
return res
}
for head != nil {
res = append(res, head.Val)
head = head.Next
}
for i, j := 0, len(res)-1; i < j; i, j = i+1, j-1 {
res[i], res[j] = res[j], res[i]
}
return res
}
剑指 Offer 07. 重建二叉树
/**
* Definition for a binary tree node.
* type TreeNode struct {
* Val int
* Left *TreeNode
* Right *TreeNode
* }
*/
func buildTree(preorder []int, inorder []int) *TreeNode {
if len(preorder) == 0 || len(inorder) == 0 {
return nil
}
root := &TreeNode{
Val: preorder[0],
}
for pos, val := range inorder {
if val == preorder[0] {
root.Left = buildTree(preorder[1:1+pos], inorder[:1+pos])
root.Right = buildTree(preorder[pos+1:], inorder[pos+1:])
}
}
return root
}
剑指 Offer 09. 用两个栈实现队列
type Stack []int
func (s *Stack) Push(val int) {
*s = append(*s, val)
}
func (s *Stack) Pop() int {
res := (*s)[len(*s)-1]
*s = (*s)[:len(*s)-1]
return res
}
type CQueue struct {
Head Stack
Tail Stack
}
func Constructor() CQueue {
return CQueue{}
}
func (this *CQueue) AppendTail(value int) {
this.Tail.Push(value)
}
func (this *CQueue) DeleteHead() int {
if len(this.Head) == 0 {
if len(this.Tail) == 0 {
return -1
}
for len(this.Tail) != 0 {
this.Head.Push(this.Tail.Pop())
}
}
return this.Head.Pop()
}
/**
* Your CQueue object will be instantiated and called as such:
* obj := Constructor();
* obj.AppendTail(value);
* param_2 := obj.DeleteHead();
*/
剑指 Offer 10- I. 斐波那契数列
func fib(n int) int {
if n <= 1 {
return n
}
first, second := 0, 1
for i := 2; i <= n; i++ {
first, second = second, (first+second)%1000000007
}
return second
}
剑指 Offer 10- II. 青蛙跳台阶问题
func numWays(n int) int {
if n == 0 || n == 1 {
return 1
}
first, second := 1, 1
for i := 2; i <= n; i++ {
first, second = second, (first+second)%1000000007
}
return second
}
剑指 Offer 11. 旋转数组的最小数字
func minArray(numbers []int) int {
i, j := 0, len(numbers)-1
for i < j {
m := i + (j-i)/2
// 找旋转数据最小值的,与右边界比较
if numbers[m] < numbers[j] {
// 最小值位于 [i, m] 之间
j = m
} else if numbers[m] > numbers[j] {
// 最小值位于 [m + 1, j] 之间
i = m + 1
} else {
// 不能确定,只能逐步减小范围
j--
}
}
return numbers[i]
}
剑指 Offer 12. 矩阵中的路径
var nexts = [][]int{
{0, 1},
{0, -1},
{1, 0},
{-1, 0},
}
func exist2(board [][]byte, visited [][]bool, word string, i, j int) bool {
if len(word) == 0 {
return true
}
if i < 0 || i >= len(board) || j < 0 || j >= len(board[0]) || visited[i][j] || board[i][j] != word[0] {
return false
}
visited[i][j] = true
for _, next := range nexts {
if exist2(board, visited, word[1:], i+next[0], j+next[1]) {
return true
}
}
visited[i][j] = false
return false
}
func exist(board [][]byte, word string) bool {
visited := make([][]bool, len(board))
for i := 0; i < len(board); i++ {
visited[i] = make([]bool, len(board[0]))
}
for i := 0; i < len(board); i++ {
for j := 0; j < len(board[0]); j++ {
if exist2(board, visited, word, i, j) {
return true
}
}
}
return false
}
剑指 Offer 13. 机器人的运动范围
var nexts = [][]int{
{0, 1},
{0, -1},
{-1, 0},
{1, 0},
}
func calNum(num int) int {
res := 0
for num != 0 {
res += num%10
num /= 10
}
return res
}
func dfs(board [][]int, i, j, k int) {
if i < 0 || i >= len(board) || j < 0 || j >= len(board[0]) || board[i][j] == -1 || board[i][j] > k {
return
}
board[i][j] = -1
for _, next := range nexts {
dfs(board, i+next[0], j+next[1], k)
}
}
func movingCount(m int, n int, k int) int {
board := make([][]int, m)
for i := 0; i < m; i++ {
board[i] = make([]int, n)
}
for i := 0; i < m; i++ {
for j := 0; j < n; j++ {
board[i][j] = calNum(i) + calNum(j)
}
}
dfs(board, 0, 0, k)
res := 0
for i := 0; i < m; i++ {
for j := 0; j < n; j++ {
if board[i][j] == -1 {
res++
}
}
}
return res
}
剑指 Offer 14- I. 剪绳子
func max(i, j int) int {
if i < j {
return j
}
return i
}
func cuttingRope(n int) int {
// dp[i] 表示长度为 i 的绳子剪成至少 2 段的最大乘积
dp := make([]int, n+1)
dp[1] = 1
for i := 2; i <= n; i++ {
for j := 1; j <= i/2; j++ {
dp[i] = max(dp[i], max(dp[j]*dp[i-j], max(dp[j]*(i-j), max(j*dp[i-j], j*(i-j)))))
}
}
return dp[n]
}
剑指 Offer 14- II. 剪绳子 II
func cuttingRope(n int) int {
if n == 2 {
return 1
} else if n == 3 {
return 2
} else if n == 4 {
return 4
}
// 如果绳子大于 4,尽量拆成长度为 3 的段,但是最后一段不能为 1,只能为 2/3/4
res := 1
for n > 4 {
res = res * 3 % 1000000007
n -= 3
}
return res * n % 1000000007;
}
剑指 Offer 15. 二进制中1的个数
func hammingWeight(num uint32) int {
res := 0
for num != 0 {
res++
// 位计算 n&(n-1),会把该整数二进制的最右边的 1 变成 0
num = num & (num-1)
}
return res
}
剑指 Offer 16. 数值的整数次方
func myPow2(x float64, n int) float64 {
if n == 0 {
return 1.0
}
if n % 2 == 0 {
res := myPow2(x, n/2)
return res * res
} else {
return x * myPow2(x, n-1)
}
}
func myPow(x float64, n int) float64 {
if n == 0 {
return 1.0
}
if n < 0 {
return 1.0/myPow2(x, -n)
} else {
return myPow2(x, n)
}
}
剑指 Offer 17. 打印从1到最大的n位数
func printNumbers(n int) []int {
max := int(math.Pow(10, float64(n))) - 1
res := make([]int, max-1)
for i := 1; i < max; i++ {
res[i-1] = i
}
return res
}
剑指 Offer 18. 删除链表的节点
/**
* Definition for singly-linked list.
* type ListNode struct {
* Val int
* Next *ListNode
* }
*/
func deleteNode(head *ListNode, val int) *ListNode {
if head == nil {
return nil
}
if head.Val == val {
return head.Next
}
slow, fast := head, head.Next
for fast != nil {
if fast.Val == val {
slow.Next = fast.Next
break
}
slow, fast = slow.Next, fast.Next
}
return head
}
剑指 Offer 19. 正则表达式匹配
func isMatch2(s, p string, i, j int) bool {
if j == len(p) {
return i == len(s)
}
if i == len(s) {
if (len(p)-j)%2 != 0 {
return false
}
j++
for ; j < len(p); {
if p[j] != '*' {
return false
}
j += 2
}
return true
}
flag := false
if j+1 < len(p) && p[j+1] == '*' {
if s[i] == p[j] || p[j] == '.' {
flag = isMatch2(s, p, i, j+2) || isMatch2(s, p, i+1, j)
} else {
flag = isMatch2(s, p, i, j+2)
}
} else {
if s[i] == p[j] || p[j] == '.' {
flag = isMatch2(s, p, i+1, j+1)
} else {
flag = false
}
}
return flag
}
func isMatch(s string, p string) bool {
return isMatch2(s, p, 0, 0)
}
剑指 Offer 20. 表示数值的字符串
func isFloat(s string) bool {
if len(s) == 0 {
return false
}
i := 0
if s[i] == '+' || s[i] == '-' {
i++
}
if len(s)-i < 2 {
return false
}
isDot := false
for i < len(s) {
if s[i] == '.' {
if isDot {
return false
}
isDot = true
} else if !unicode.IsDigit(rune(s[i])) {
return false
}
i++
}
return true
}
func isInteger(s string) bool {
if len(s) == 0 {
return false
}
i := 0
if s[i] == '+' || s[i] == '-' {
i++
}
if i == len(s) {
return false
}
for i < len(s) {
if !unicode.IsDigit(rune(s[i])) {
return false
}
i++
}
return true
}
func isNumber(s string) bool {
s = strings.TrimSpace(s)
if len(s) == 0 {
return false
}
isE, pos := false, 0
for i := 0; i < len(s); i++ {
if s[i] == 'e' || s[i] == 'E' {
if isE {
return false
}
isE, pos = true, i
}
}
if isE {
return (isFloat(s[:pos]) || isInteger(s[:pos])) && isInteger(s[pos+1:])
} else {
return isFloat(s) || isInteger(s)
}
}
剑指 Offer 21. 调整数组顺序使奇数位于偶数前面
func exchange(nums []int) []int {
i, j := 0, len(nums)
for i < j {
if nums[i]%2 != 0 {
i++
} else {
j--
nums[i], nums[j] = nums[j], nums[i]
}
}
return nums
}
剑指 Offer 22. 链表中倒数第k个节点
/**
* Definition for singly-linked list.
* type ListNode struct {
* Val int
* Next *ListNode
* }
*/
func getKthFromEnd(head *ListNode, k int) *ListNode {
if head == nil {
return head
}
slow, fast := head, head
for k > 0 {
fast = fast.Next
k--
}
for fast != nil {
slow, fast = slow.Next, fast.Next
}
return slow
}
剑指 Offer 24. 反转链表
/**
* Definition for singly-linked list.
* type ListNode struct {
* Val int
* Next *ListNode
* }
*/
func reverseList(head *ListNode) *ListNode {
if head == nil || head.Next == nil {
return head
}
var pre, cur, next *ListNode = nil, head, head
for cur != nil {
next = cur.Next
cur.Next = pre
pre, cur = cur, next
}
return pre
}
剑指 Offer 25. 合并两个排序的链表
/**
* Definition for singly-linked list.
* type ListNode struct {
* Val int
* Next *ListNode
* }
*/
func mergeTwoLists(l1 *ListNode, l2 *ListNode) *ListNode {
newHead := &ListNode{Val:-1}
node := newHead
for l1 != nil && l2 != nil {
if l1.Val <= l2.Val {
node.Next = l1
l1 = l1.Next
} else {
node.Next = l2
l2 = l2.Next
}
node = node.Next
}
if l1 != nil {
node.Next = l1
} else {
node.Next = l2
}
return newHead.Next
}
剑指 Offer 26. 树的子结构
/**
* Definition for a binary tree node.
* type TreeNode struct {
* Val int
* Left *TreeNode
* Right *TreeNode
* }
*/
func isEqual(A *TreeNode, B *TreeNode) bool {
if B == nil {
return true
}
if A == nil || A.Val != B.Val {
return false
}
return isEqual(A.Left, B.Left) && isEqual(A.Right, B.Right)
}
func isSubStructure(A *TreeNode, B *TreeNode) bool {
if A == nil || B == nil {
return false
}
if A.Val == B.Val && isEqual(A, B) {
return true
}
return isSubStructure(A.Left, B) || isSubStructure(A.Right, B)
}
剑指 Offer 27. 二叉树的镜像
/**
* Definition for a binary tree node.
* type TreeNode struct {
* Val int
* Left *TreeNode
* Right *TreeNode
* }
*/
func mirrorTree(root *TreeNode) *TreeNode {
if root == nil {
return root
}
root.Left, root.Right = root.Right, root.Left
mirrorTree(root.Left)
mirrorTree(root.Right)
return root
}
剑指 Offer 28. 对称的二叉树
/**
* Definition for a binary tree node.
* type TreeNode struct {
* Val int
* Left *TreeNode
* Right *TreeNode
* }
*/
func isSymmetric2(root1, root2 *TreeNode) bool {
if root1 == nil && root2 == nil {
return true
}
if root1 == nil || root2 == nil || root1.Val != root2.Val {
return false
}
return isSymmetric2(root1.Left, root2.Right) && isSymmetric2(root1.Right, root2.Left)
}
func isSymmetric(root *TreeNode) bool {
if root == nil {
return true
}
return isSymmetric2(root.Left, root.Right)
}
剑指 Offer 29. 顺时针打印矩阵
func print(matrix [][]int, i1, j1, i2, j2 int) []int {
var res []int
if i1 == i2 {
for j := j1; j <= j2; j++ {
res = append(res, matrix[i1][j])
}
return res
}
if j1 == j2 {
for i := i1; i <= i2; i++ {
res = append(res, matrix[i][j1])
}
return res
}
for j := j1; j <= j2; j++ {
res = append(res, matrix[i1][j])
}
for i := i1+1; i < i2; i++ {
res = append(res, matrix[i][j2])
}
for j := j2; j >= j1; j-- {
res = append(res, matrix[i2][j])
}
for i := i2-1; i > i1; i-- {
res = append(res, matrix[i][j1])
}
return res
}
func spiralOrder(matrix [][]int) []int {
var res []int
if len(matrix) == 0 || len(matrix[0]) == 0 {
return res
}
i1, j1, i2, j2 := 0, 0, len(matrix)-1, len(matrix[0])-1
for i1 <= i2 && j1 <= j2 {
res = append(res, print(matrix, i1, j1, i2, j2)...)
i1++
i2--
j1++
j2--
}
return res
}
剑指 Offer 30. 包含min函数的栈
type Stack []int
func (s *Stack) Push(val int) {
*s = append(*s, val)
}
func (s *Stack) Pop() int {
res := (*s)[len(*s)-1]
*s = (*s)[:len(*s)-1]
return res
}
func (s *Stack) Peek() int {
return (*s)[len(*s)-1]
}
func min(a, b int) int {
if a > b {
return b
}
return a
}
type MinStack struct {
data Stack
min Stack
}
/** initialize your data structure here. */
func Constructor() MinStack {
return MinStack{}
}
func (this *MinStack) Push(x int) {
this.data.Push(x)
if len(this.min) == 0 {
this.min.Push(x)
} else {
this.min.Push(min(this.min.Peek(), x))
}
}
func (this *MinStack) Pop() {
this.data.Pop()
this.min.Pop()
}
func (this *MinStack) Top() int {
return this.data.Peek()
}
func (this *MinStack) Min() int {
return this.min.Peek()
}
/**
* Your MinStack object will be instantiated and called as such:
* obj := Constructor();
* obj.Push(x);
* obj.Pop();
* param_3 := obj.Top();
* param_4 := obj.Min();
*/
剑指 Offer 31. 栈的压入、弹出序列
func validateStackSequences(pushed []int, popped []int) bool {
if len(pushed) != len(popped) {
return false
}
var stack []int
j := 0
for i := 0; i < len(pushed); i++ {
stack = append(stack, pushed[i])
for len(stack) != 0 && stack[len(stack)-1] == popped[j] {
stack = stack[:len(stack)-1]
j++
}
}
return len(stack) == 0
}
剑指 Offer 32 - I. 从上到下打印二叉树
/**
* Definition for a binary tree node.
* type TreeNode struct {
* Val int
* Left *TreeNode
* Right *TreeNode
* }
*/
func levelOrder(root *TreeNode) []int {
var res []int
if root == nil {
return res
}
var queue []*TreeNode
queue = append(queue, root)
for len(queue) != 0 {
size := len(queue)
for i := 0; i < size; i++ {
node := queue[i]
res = append(res, node.Val)
if node.Left != nil {
queue = append(queue, node.Left)
}
if node.Right != nil {
queue = append(queue, node.Right)
}
}
queue = queue[size:]
}
return res
}
剑指 Offer 32 - II. 从上到下打印二叉树 II
/**
* Definition for a binary tree node.
* type TreeNode struct {
* Val int
* Left *TreeNode
* Right *TreeNode
* }
*/
func levelOrder(root *TreeNode) [][]int {
var res [][]int
if root == nil {
return res
}
var queue []*TreeNode
queue = append(queue, root)
for len(queue) != 0 {
size := len(queue)
var list []int
for i := 0; i < size; i++ {
node := queue[i]
list = append(list, node.Val)
if node.Left != nil {
queue = append(queue, node.Left)
}
if node.Right != nil {
queue = append(queue, node.Right)
}
}
queue = queue[size:]
res = append(res, list)
}
return res
}
剑指 Offer 32 - III. 从上到下打印二叉树 III
/**
* Definition for a binary tree node.
* type TreeNode struct {
* Val int
* Left *TreeNode
* Right *TreeNode
* }
*/
func levelOrder(root *TreeNode) [][]int {
var res [][]int
if root == nil {
return res
}
var queue []*TreeNode
queue = append(queue, root)
flag := true
for len(queue) != 0 {
size := len(queue)
list := make([]int, size)
for i := 0; i < size; i++ {
node := queue[i]
if flag {
list[i] = node.Val
} else {
list[size-1-i] = node.Val
}
if node.Left != nil {
queue = append(queue, node.Left)
}
if node.Right != nil {
queue = append(queue, node.Right)
}
}
queue = queue[size:]
res = append(res, list)
flag = !flag
}
return res
}
剑指 Offer 33. 二叉搜索树的后序遍历序列
func verifyPostorder(postorder []int) bool {
if len(postorder) == 0 {
return true
}
root := postorder[len(postorder)-1]
i, pos := 0, 0
for postorder[i] < root {
i++
}
pos = i
for i < len(postorder)-1 {
if postorder[i] <= root {
return false
}
i++
}
return verifyPostorder(postorder[:pos]) && verifyPostorder(postorder[pos:len(postorder)-1])
}
剑指 Offer 34. 二叉树中和为某一值的路径
/**
* Definition for a binary tree node.
* type TreeNode struct {
* Val int
* Left *TreeNode
* Right *TreeNode
* }
*/
func pathSum2(root *TreeNode, target int, path *[]int, res *[][]int) {
if root == nil {
return
}
target -= root.Val
*path = append(*path, root.Val)
if root.Left == nil && root.Right == nil && target == 0 {
temp := make([]int, len(*path))
copy(temp, *path)
*res = append(*res, temp)
}
pathSum2(root.Left, target, path, res)
pathSum2(root.Right, target, path, res)
*path = (*path)[:len(*path)-1]
}
func pathSum(root *TreeNode, target int) [][]int {
var res [][]int
if root == nil {
return res
}
var path []int
pathSum2(root, target, &path, &res)
return res
}
剑指 Offer 35. 复杂链表的复制
/**
* Definition for a Node.
* type Node struct {
* Val int
* Next *Node
* Random *Node
* }
*/
func copyRandomList(head *Node) *Node {
node := head
for node != nil {
next := node.Next
node.Next = &Node{Val:node.Val}
node.Next.Next = next
node = node.Next.Next
}
node = head
for node != nil {
if node.Random != nil {
node.Next.Random = node.Random.Next
}
node = node.Next.Next
}
newHead1, newHead2 := &Node{Val:-1}, &Node{Val:-1}
node1, node2, node := newHead1, newHead2, head
for node != nil {
node1.Next, node2.Next = node, node.Next
node1, node2 = node1.Next, node2.Next
node = node.Next.Next
}
node1.Next = nil
return newHead2.Next
}
剑指 Offer 38. 字符串的排列
func permutation2(sBytes []byte, visited []bool, path *[]byte, res *[]string) {
if len(*path) == len(sBytes) {
*res = append(*res, string(*path))
return
}
for i := 0; i < len(sBytes); i++ {
if visited[i] {
continue
}
if i >= 1 && sBytes[i-1] == sBytes[i] && !visited[i-1] {
continue
}
*path = append(*path, sBytes[i])
visited[i] = true
permutation2(sBytes, visited, path, res)
visited[i] = false
*path = (*path)[:len(*path)-1]
}
}
func permutation(s string) []string {
var res []string
if len(s) == 0 {
return res
}
sBytes := []byte(s)
sort.Slice(sBytes, func(i, j int) bool {
return sBytes[i] < sBytes[j]
})
visited := make([]bool, len(s))
var path []byte
permutation2(sBytes, visited, &path, &res)
return res
}
剑指 Offer 39. 数组中出现次数超过一半的数字
func majorityElement(nums []int) int {
// Boyer-Moore 投票算法
res, cnt := 0, 0
for _, num := range nums {
if cnt == 0 {
res, cnt = num, 1
} else if num == res {
cnt++
} else {
cnt--
}
}
return res
}
剑指 Offer 40. 最小的k个数
func quickSort(arr []int, i, j, k int) {
if i < j {
m := sort(arr, i, j)
if m < k {
quickSort(arr, m+1, j, k)
} else if m > k {
quickSort(arr, i, m-1, k)
}
}
}
func sort(arr []int, i, j int) int {
// 将第一个数作为 target,先右边再左边
start, target := i, arr[i]
for i < j {
// 右边是大于 target 的数
for i < j && arr[j] > target {
j--
}
// 左边是小于等于 target 的数
for i < j && arr[i] <= target {
i++
}
arr[i], arr[j] = arr[j], arr[i]
}
arr[start], arr[i] = arr[i], arr[start]
return i
}
func getLeastNumbers(arr []int, k int) []int {
// 使用快速排序
quickSort(arr, 0, len(arr)-1, k-1)
return arr[:k]
}
剑指 Offer 41. 数据流中的中位数
type minHeap []int
func (h minHeap) Len() int {
return len(h)
}
func (h minHeap) Swap(i, j int) {
h[i], h[j] = h[j], h[i]
}
func (h minHeap) Less(i, j int) bool {
return h[i] < h[j]
}
func (h *minHeap) Push(x interface{}) {
*h = append(*h, x.(int))
}
func (h *minHeap) Pop() interface{} {
x := (*h)[len(*h)-1]
*h = (*h)[:len(*h)-1]
return x
}
type maxHeap []int
func (h maxHeap) Len() int {
return len(h)
}
func (h maxHeap) Swap(i, j int) {
h[i], h[j] = h[j], h[i]
}
func (h maxHeap) Less(i, j int) bool {
return h[i] > h[j]
}
func (h *maxHeap) Push(x interface{}) {
*h = append(*h, x.(int))
}
func (h *maxHeap) Pop() interface{} {
x := (*h)[len(*h)-1]
*h = (*h)[:len(*h)-1]
return x
}
type MedianFinder struct {
// left 是大顶堆,right 是小顶堆
left maxHeap
right minHeap
}
/** initialize your data structure here. */
func Constructor() MedianFinder {
return MedianFinder{}
}
func (this *MedianFinder) AddNum(num int) {
if len(this.left) == len(this.right) {
heap.Push(&this.right, num)
heap.Push(&this.left, heap.Pop(&this.right))
} else {
heap.Push(&this.left, num)
heap.Push(&this.right, heap.Pop(&this.left))
}
}
func (this *MedianFinder) FindMedian() float64 {
if len(this.left) == len(this.right) {
num1, num2 := this.left[0], this.right[0]
return float64(num1+num2) / 2.0
} else {
return float64(this.left[0])
}
}
/**
* Your MedianFinder object will be instantiated and called as such:
* obj := Constructor();
* obj.AddNum(num);
* param_2 := obj.FindMedian();
*/
剑指 Offer 42. 连续子数组的最大和
func max(a, b int) int {
if a > b {
return a
}
return b
}
func maxSubArray(nums []int) int {
// dp[i]:以 nums[i] 结尾的连续子数组的最大和
dp := make([]int, len(nums))
dp[0] = nums[0]
res := dp[0]
for i := 1; i < len(nums); i++ {
dp[i] = max(dp[i-1]+nums[i], nums[i])
res = max(res, dp[i])
}
return res
}
剑指 Offer 43. 1~n 整数中 1 出现的次数
func countDigitOne(n int) int {
if n == 0 {
return 0
}
s := strconv.Itoa(n)
high := int(s[0] - '0')
pow := int(math.Pow(10, float64(len(s)-1)))
last := n - pow*high
if high == 1 {
// 例如:1234,拆为 1-999 和 1000-1234 两部分:
// countDigitOne(pow - 1):1-999 出现 1 的次数
// last + 1: 1000-1234 千位上出现 1 的次数
// countDigitOne(last):1000-1234 除千位外出现 1 的次数
return countDigitOne(pow-1) + last + 1 + countDigitOne(last)
} else {
// 例如:3234,拆为 1-999、1000-2999 和 3000-3234 三部分:
// countDigitOne(pow - 1):1-999 出现 1 的次数
// pow:1000-2999:千位上出现 1 的次数
// countDigitOne(pow - 1) * (high - 1):1000-2999 除千位外出现 1 的次数
// countDigitOne(last):3000-3234 出现 1 的次数
return countDigitOne(pow-1)*high + pow + countDigitOne(last)
}
}
剑指 Offer 44. 数字序列中某一位的数字
func findNthDigit(n int) int {
if n == 0 {
return 0
}
// length 是数字的字符长度,base 是基数,cnt 为长度为 length 的数字数目
// 例如:10-99 之间的数字,len 为 2,base 为 10,cnt 为 90
length, base := 1, 1
cnt := length * 9 * base
for n-cnt > 0 {
n -= cnt
length++
base *= 10
cnt = length * 9 * base
}
num := base + n/length
if n%length == 0 {
s := strconv.Itoa(num - 1)
return int(s[len(s)-1] - '0')
} else {
s := strconv.Itoa(num)
return int(s[n%length-1] - '0')
}
}
剑指 Offer 45. 把数组排成最小的数
func minNumber(nums []int) string {
ss := make([]string, len(nums))
for i, num := range nums {
ss[i] = strconv.Itoa(num)
}
sort.Slice(ss, func(i, j int) bool{
return ss[i]+ss[j] < ss[j]+ss[i]
})
var sb strings.Builder
for _, s := range ss {
sb.WriteString(s)
}
return sb.String()
}
剑指 Offer 46. 把数字翻译成字符串
func translateNum(num int) int {
s := strconv.Itoa(num)
// dp[i]:s[:i] 所能组成的翻译方法数
dp := make([]int, len(s))
dp[0] = 1
for i := 1; i < len(s); i++ {
dp[i] = dp[i-1]
if s[i-1] == '1' || (s[i-1] == '2' && '0' <= s[i] && s[i] <= '5') {
if i >= 2 {
dp[i] += dp[i-2]
} else {
dp[i] += 1
}
}
}
return dp[len(s)-1]
}
剑指 Offer 47. 礼物的最大价值
func max(a, b int) int {
if a > b {
return a
}
return b
}
func maxValue(grid [][]int) int {
res := 0
m, n := len(grid), len(grid[0])
dp := make([][]int, m)
for i := 0; i < m; i++ {
dp[i] = make([]int, n)
}
res, dp[0][0] = grid[0][0], grid[0][0]
for j := 1; j < n; j++ {
dp[0][j] = dp[0][j-1] + grid[0][j]
res = max(res, dp[0][j])
}
for i := 1; i < m; i++ {
dp[i][0] = dp[i-1][0] + grid[i][0]
res = max(res, dp[i][0])
}
for i := 1; i < m; i++ {
for j := 1; j < n; j++ {
dp[i][j] = max(dp[i-1][j], dp[i][j-1]) + grid[i][j]
res = max(res, dp[i][j])
}
}
return res
}
剑指 Offer 48. 最长不含重复字符的子字符串
func max(a, b int) int {
if a > b {
return a
}
return b
}
func lengthOfLongestSubstring(s string) int {
// 存储字符在字符串中的位置
hashMap := make(map[byte]int)
i, res := 0, 0
for j := 0; j < len(s); j++ {
if pos, ok := hashMap[s[j]]; ok {
i = max(i, pos+1)
}
hashMap[s[j]] = j
res = max(res, j-i+1)
}
return res
}
剑指 Offer 49. 丑数
func min(a, b int) int {
if a < b {
return a
}
return b
}
func nthUglyNumber(n int) int {
// dp[i]:第 i 个丑数
dp := make([]int, n+1)
dp[1] = 1
i2, i3, i5 := 1, 1, 1
for i := 2; i <= n; i++ {
dp[i] = min(dp[i2]*2, min(dp[i3]*3, dp[i5]*5))
for dp[i2]*2 <= dp[i] {
i2++
}
for dp[i3]*3 <= dp[i] {
i3++
}
for dp[i5]*5 <= dp[i] {
i5++
}
}
return dp[n]
}
剑指 Offer 50. 第一个只出现一次的字符
func firstUniqChar(s string) byte {
cnts := make([]int, 26)
for _, ch := range s {
cnts[int(ch-'a')]++
}
for _, ch := range s {
if cnts[int(ch-'a')] == 1 {
return byte(ch)
}
}
return ' '
}
剑指 Offer 51. 数组中的逆序对
var res int
func sort(nums, temp []int, i, j int) {
if i < j {
m := i + (j-i)/2
sort(nums, temp, i, m)
sort(nums, temp, m+1, j)
merge(nums, temp, i, m, j)
}
}
func merge(nums, temp []int, i, m, j int) {
pos, i1, i2 := i, i, m+1
for i1 <= m && i2 <= j {
if nums[i1] <= nums[i2] {
temp[pos] = nums[i1]
res += i2 - m - 1
i1++
} else {
temp[pos] = nums[i2]
i2++
}
pos++
}
if i1 <= m {
copy(temp[pos:j+1], nums[i1:m+1])
res += (m-i1+1) * (j-m)
}
if i2 <= j {
copy(temp[pos:j+1], nums[i2:j+1])
}
copy(nums[i:j+1], temp[i:j+1])
}
func reversePairs(nums []int) int {
res = 0
// 使用归并排序
sort(nums, make([]int, len(nums)), 0, len(nums)-1)
return res
}
剑指 Offer 52. 两个链表的第一个公共节点
/**
* Definition for singly-linked list.
* type ListNode struct {
* Val int
* Next *ListNode
* }
*/
func getIntersectionNode(headA, headB *ListNode) *ListNode {
if headA == nil || headB == nil {
return nil
}
node1, node2 := headA, headB
flag := false
for node1 != node2 {
node1 = node1.Next
if node1 == nil {
if flag {
return nil
}
flag, node1 = true, headB
}
node2 = node2.Next
if node2 == nil {
node2 = headA
}
}
return node1
}
剑指 Offer 53 - I. 在排序数组中查找数字 I
func searchLeft(nums []int, target int) int {
i, j := 0, len(nums)-1
for i <= j {
m := i + (j-i)/2
if nums[m] > target {
j = m - 1
} else if nums[m] < target {
i = m + 1
} else {
j = m - 1
}
}
if i >= len(nums) || nums[i] != target {
return -1
}
return i
}
func searchRight(nums []int, target int) int {
i, j := 0, len(nums)-1
for i <= j {
m := i + (j-i)/2
if nums[m] > target {
j = m - 1
} else if nums[m] < target {
i = m + 1
} else {
i = m + 1
}
}
if j < 0 || nums[j] != target {
return -1
}
return j
}
func search(nums []int, target int) int {
left := searchLeft(nums, target)
if left == -1 {
return 0
}
right := searchRight(nums, target)
return right - left + 1
}
剑指 Offer 53 - II. 0~n-1中缺失的数字
func missingNumber(nums []int) int {
res := 0
for _, num := range nums {
res ^= num
}
for i := 0; i <= len(nums); i++ {
res ^= i
}
return res
}
剑指 Offer 54. 二叉搜索树的第k大节点
/**
* Definition for a binary tree node.
* type TreeNode struct {
* Val int
* Left *TreeNode
* Right *TreeNode
* }
*/
var kVal, res int
func kthLargest2(root *TreeNode) bool {
if root == nil {
return false
}
if kthLargest2(root.Right) {
return true
}
kVal--
if kVal == 0 {
res = root.Val
return true
}
if kthLargest2(root.Left) {
return true
}
return false
}
func kthLargest(root *TreeNode, k int) int {
kVal, res = k, 0
kthLargest2(root)
return res
}
剑指 Offer 55 - I. 二叉树的深度
/**
* Definition for a binary tree node.
* type TreeNode struct {
* Val int
* Left *TreeNode
* Right *TreeNode
* }
*/
func max(a, b int) int {
if a > b {
return a
}
return b
}
func maxDepth(root *TreeNode) int {
if root == nil {
return 0
}
left, right := maxDepth(root.Left), maxDepth(root.Right)
return max(left, right) + 1
}
剑指 Offer 55 - II. 平衡二叉树
/**
* Definition for a binary tree node.
* type TreeNode struct {
* Val int
* Left *TreeNode
* Right *TreeNode
* }
*/
func max(a, b int) int {
if a > b {
return a
}
return b
}
func maxDepth(root *TreeNode) int {
if root == nil {
return 0
}
left, right := maxDepth(root.Left), maxDepth(root.Right)
return max(left, right) + 1
}
func isBalanced(root *TreeNode) bool {
if root == nil {
return true
}
left, right := maxDepth(root.Left), maxDepth(root.Right)
if math.Abs(float64(left-right)) > 1.0 {
return false
}
return isBalanced(root.Left) && isBalanced(root.Right)
}
剑指 Offer 56 - I. 数组中数字出现的次数
func singleNumbers(nums []int) []int {
num := 0
for i := 0; i < len(nums); i++ {
num ^= nums[i]
}
// num & -num 会获得 num 的位级表示中最低的那一位 1
// 例如:num 为 10110100,-num 为 ~num + 1 = 01001100,num & -num 为 00000100
num &= -num
res := make([]int, 2)
for i := 0; i < len(nums); i++ {
if num & nums[i] == 0 {
res[0] ^= nums[i]
} else {
res[1] ^= nums[i]
}
}
return res
}
剑指 Offer 56 - II. 数组中数字出现的次数 II
func singleNumber(nums []int) int {
res := 0
for i := 0; i < 32; i++ {
cnt := 0
// 统计所有数字的二进制在第 i 位上 1 的数字
for _, num := range nums {
cnt += (num >> i) & 1
}
res |= (cnt % 3) << i
}
return res
}
剑指 Offer 57. 和为s的两个数字
func twoSum(nums []int, target int) []int {
i, j := 0, len(nums)-1
for i < j {
sum := nums[i] + nums[j]
if sum == target {
return []int{nums[i], nums[j]}
} else if sum < target {
i++
} else {
j--
}
}
return []int{}
}
剑指 Offer 57 - II. 和为s的连续正数序列
func findContinuousSequence(target int) [][]int {
var res [][]int
if target <= 2 {
return res
}
i, j, sum := 1, 2, 3
for i < j {
if sum == target {
list := make([]int, j-i+1)
for k := i; k <= j; k++ {
list[k-i] = k
}
res = append(res, list)
sum -= i
i++
j++
sum += j
} else if sum < target {
j++
sum += j
} else {
sum -= i
i++
}
}
return res
}
剑指 Offer 58 - I. 翻转单词顺序
func reverseWords(s string) string {
ss := strings.Fields(s)
for i, j := 0, len(ss)-1; i < j; i, j = i+1, j-1 {
ss[i], ss[j] = ss[j], ss[i]
}
return strings.Join(ss, " ")
}
剑指 Offer 58 - II. 左旋转字符串
// 方式一
func reverseLeftWords(s string, n int) string {
return s[n:] + s[:n]
}
// 方式二
func reverse(b []byte, i, j int) {
for i < j {
b[i], b[j] = b[j], b[i]
i++
j--
}
}
func reverseLeftWords(s string, n int) string {
b := []byte(s)
reverse(b, 0, n-1)
reverse(b, n, len(b)-1)
reverse(b, 0, len(b)-1)
return string(b)
}
剑指 Offer 59 - I. 滑动窗口的最大值
func offer(deque *[]int, val int) {
for len(*deque) != 0 && (*deque)[len(*deque)-1] < val {
*deque = (*deque)[:len(*deque)-1]
}
*deque = append(*deque, val)
}
func maxSlidingWindow(nums []int, k int) []int {
var res, deque []int
for i := 0; i < len(nums); i++ {
if i < k {
offer(&deque, nums[i])
if i == k-1 {
res = append(res, deque[0])
}
} else {
if deque[0] == nums[i-k] {
deque = deque[1:]
}
offer(&deque, nums[i])
res = append(res, deque[0])
}
}
return res
}
剑指 Offer 59 - II. 队列的最大值
type MaxQueue struct {
data []int
max []int
}
func Constructor() MaxQueue {
return MaxQueue{}
}
func (this *MaxQueue) Max_value() int {
if len(this.max) == 0 {
return -1
}
return this.max[0]
}
func (this *MaxQueue) Push_back(value int) {
this.data = append(this.data, value)
for len(this.max) != 0 && this.max[len(this.max)-1] < value {
this.max = this.max[:len(this.max)-1]
}
this.max = append(this.max, value)
}
func (this *MaxQueue) Pop_front() int {
if len(this.data) == 0 {
return -1
}
res := this.data[0]
this.data = this.data[1:]
if res == this.max[0] {
this.max = this.max[1:]
}
return res
}
/**
* Your MaxQueue object will be instantiated and called as such:
* obj := Constructor();
* param_1 := obj.Max_value();
* obj.Push_back(value);
* param_3 := obj.Pop_front();
*/
剑指 Offer 60. n个骰子的点数
func dicesProbability(n int) []float64 {
// dp[i][j]:i 个骰子掷到分数 j 的出现次数
dp := make([][]int, n+1)
for i := 0; i <= n; i++ {
dp[i] = make([]int, 6*n+1)
}
for j := 1; j <= 6; j++ {
dp[1][j] = 1
}
for i := 2; i <= n; i++ {
for j := i; j <= i*6; j++ {
for k := 1; k <= 6 && j > k; k++ {
dp[i][j] += dp[i-1][j-k]
}
}
}
sum := math.Pow(6, float64(n))
res := make([]float64, 5*n+1)
for j := n; j <= n*6; j++ {
res[j-n] = float64(dp[n][j]) / float64(sum)
}
return res
}
剑指 Offer 61. 扑克牌中的顺子
func isStraight(nums []int) bool {
sort.Ints(nums)
i, cnt := 0, 0
for i < len(nums) && nums[i] == 0 {
cnt++
i++
}
for i+1 < len(nums) {
if nums[i+1] == nums[i] {
return false
}
cnt -= nums[i+1] - nums[i] - 1
if cnt < 0 {
return false
}
i++
}
return true
}
剑指 Offer 62. 圆圈中最后剩下的数字
func lastRemaining(n int, m int) int {
if n == 1 {
return 0
}
res := 0
for i := 2; i <= n; i++ {
res = (res + m) % i
}
return res
}
剑指 Offer 63. 股票的最大利润
func max(a, b int) int {
if a > b {
return a
}
return b
}
func maxProfit(prices []int) int {
if len(prices) == 0 {
return 0
}
// dp[i][0]:第 i+1 天,手里没有股票,所能获得的最大利润
// dp[i][1]:第 i+1 天,手里有股票,所能获得的最大利润
dp := make([][2]int, len(prices))
dp[0][1] = -prices[0]
for i := 1; i < len(prices); i++ {
dp[i][0] = max(dp[i-1][0], dp[i-1][1] + prices[i])
dp[i][1] = max(dp[i-1][1], -prices[i])
}
return dp[len(prices)-1][0]
}
剑指 Offer 64. 求1+2+…+n
var res int
func dfs(n int) bool {
res += n
return n > 0 && dfs(n-1)
}
func sumNums(n int) int {
res = 0
dfs(n)
return res
}
剑指 Offer 65. 不用加减乘除做加法
func add(a int, b int) int {
if a == 0 {
return b
}
return add((a&b)<<1, a^b)
}
剑指 Offer 66. 构建乘积数组
func constructArr(a []int) []int {
res := make([]int, len(a))
temp := 1
for i := 0; i < len(a); i++ {
res[i] = temp
temp *= a[i]
}
temp = 1
for i := len(a)-1; i >= 0; i-- {
res[i] *= temp
temp *= a[i]
}
return res
}
剑指 Offer 67. 把字符串转换成整数
func strToInt(str string) int {
str = strings.TrimSpace(str)
if len(str) == 0 {
return 0
}
i := 0
var sign byte = '+'
if str[i] == '+' || str[i] == '-' {
sign = str[i]
i++
}
num := 0
for i < len(str) && unicode.IsDigit(rune(str[i])) {
num = num*10 + int(str[i] - '0')
if sign == '+' && num >= math.MaxInt32 {
return math.MaxInt32
} else if sign == '-' && -num <= math.MinInt32 {
return math.MinInt32
}
i++
}
if sign == '+' {
return num
} else {
return -num
}
}
剑指 Offer 68 - II. 二叉树的最近公共祖先
/**
* Definition for a binary tree node.
* type TreeNode struct {
* Val int
* Left *TreeNode
* Right *TreeNode
* }
*/
func lowestCommonAncestor(root, p, q *TreeNode) *TreeNode {
if root == nil || root == p || root == q {
return root
}
left := lowestCommonAncestor(root.Left, p, q)
right := lowestCommonAncestor(root.Right, p, q)
if left != nil && right != nil {
return root
}
if left == nil {
return right
} else {
return left
}
}