零钱兑换 II 零钱兑换 II
解题思路 利用动态规划 ,dp[i]
表示金额为i
的硬币组合数,边界条件是dp[0] = 1
,表示组成金额0
有一种组合数。
初始化:dp[0] = 1
遍历coins
,对于其中的每个元素coin
:
遍历i
从coin
到amount,dp[i] += dp[i-coin]
dp[amount]
为最终答案
解题代码 1 2 3 4 5 6 7 8 9 10 11 12 func change (amount int , coins []int ) int { dp := make ([]int , amount+1 ) dp[0 ] = 1 for _, coin := range coins { for i := coin; i <= amount; i++ { dp[i] += dp[i-coin] } } return dp[amount] }
打家劫舍 打家劫舍
解题思路
利用动态规划 的思路,定义二维dp
数组表示所能获取到的最大金额。其中dp[i][0]
代表不偷取i
号房屋所获得的最大金额,而dp[i][1]
代码偷取i
号房屋所获得的最大金额。
初始化:dp[0][0] = 0
、dp[0][1] = nums[0]
、dp[1][0] = dp[0][1]
、dp[1][1] = nums[1]
状态转移方程:
`dp[i][0] = max(dp[i-1][0], dp[i-1][1])``
``dp[i][1] = max(dp[i-2][1], dp[i-1][0]) + nums[i]`
返回结果:max(dp[len(nums)-1][0], dp[len(nums)-1][1])
依然是动态规划 的思路,只不过定义一维dp
数组,dp[i]
表示偷i
间房子的最大金额。
初始化:没有房子dp[0] = 0
;只有一个房子,偷这个房子即可dp[i] = nums[0]
状态转移方程:dp[i] = max(dp[i-1], dp[i-2]+nums[i-1])
,dp[i]
有两种选择,不偷第i-1
间房子(dp[i-1]
)或者偷第i-1
间房子(dp[i-2]+nums[i-1]
)。
解题代码
dp[i][0]
代表不偷取i
号房屋所获得的最大金额,而dp[i][1]
代码偷取i
号房屋所获得的最大金额
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 func rob (nums []int ) int { if len (nums) == 1 { return nums[0 ] } dp := make ([][2 ]int , len (nums)) dp[0 ][0 ] = 0 dp[0 ][1 ] = nums[0 ] dp[1 ][0 ] = dp[0 ][1 ] dp[1 ][1 ] = nums[1 ] for i := 2 ; i < len (nums); i++ { dp[i][0 ] = max(dp[i-1 ][0 ], dp[i-1 ][1 ]) dp[i][1 ] = max(dp[i-2 ][1 ], dp[i-1 ][0 ]) + nums[i] } return max(dp[len (nums)-1 ][0 ], dp[len (nums)-1 ][1 ]) } func max (n1, n2 int ) int { if n1 > n2 { return n1 } else { return n2 } }
一维dp
数组
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 func rob (nums []int ) int { dp := make ([]int , len (nums)+1 ) dp[0 ] = 0 dp[1 ] = nums[0 ] for i := 2 ; i <= len (nums); i++ { dp[i] = max(dp[i-1 ], dp[i-2 ]+nums[i-1 ]) } return dp[len (nums)] } func max (n1, n2 int ) int { if n1 > n2 { return n1 } return n2 }
奇偶链表 奇偶链表
解题思路 将索引为偶数的节点全部从原链表中取下来 ,并组成一个新的偶数链表,那么原链表就是奇数链表。最后,将偶数链表挂到奇数链表之后即可。
解题代码 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 func oddEvenList (head *ListNode) *ListNode { if head == nil { return head } evenListHead := new (ListNode) evenListTrail := evenListHead p := head oddListTrail := p for p != nil && p.Next != nil { temp := p.Next p.Next = temp.Next temp.Next = nil evenListTrail.Next = temp evenListTrail = evenListTrail.Next p = p.Next if p != nil { oddListTrail = p } } oddListTrail.Next = evenListHead.Next return head }
Pow(x,n) Pow(x, n)
解题思路 快速幂 ,如2^10
可以划分为两个2^5
相乘,而2^5
可以划分为2
与两个2^2
相乘。如此划分,直到划分为2^0=1
解题代码
递归
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 func myPow (x float64 , n int ) float64 { if n > 0 { return quickMul(x, n) } else { return 1.0 / quickMul(x, -n) } } func quickMul (x float64 , n int ) float64 { if n == 0 { return 1 } y := quickMul(x, n/2 ) if n % 2 == 1 { return x*y*y } else { return y*y } }
迭代
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 func myPow (x float64 , n int ) float64 { if n > 0 { return quickMul(x, n) } else { return 1.0 / quickMul(x, -n) } } func quickMul (x float64 , n int ) float64 { ans := 1.0 x_contribute := x for n > 0 { if n % 2 == 1 { ans *= x_contribute } x_contribute *= x_contribute n /= 2 } return ans }
二叉搜索树中第K小的元素 二叉搜索树中第K小的元素
解题思路
利用二叉搜索树的特性,二叉搜索树的中序遍历是个递增有序序列 ,所以可以利用数组记录前k
个遍历节点,当第k
小的元素遍历完成后跳出循环
计算左子树的节点总数为left
若left==k-1
,则当前根节点恰好 是第k
小的元素
若left>k-1
,则第k
小的元素在左子树 中,到左子树递归寻找第k
小的元素
若left<k-1
,则第k
小的节点在右子树 中,第k
小的节点也就是右子树的第k-left-1
小的节点
解题代码
二叉搜索树的中序遍历
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 func kthSmallest (root *TreeNode, k int ) int { firstKth := make ([]int , k) visitedNum := 0 stack := make ([]*TreeNode, 0 ) cur := root for len (stack) > 0 || cur != nil { for cur != nil { stack = append (stack, cur) cur = cur.Left } if len (stack) > 0 { cur = stack[len (stack)-1 ] stack = stack[:len (stack)-1 ] if visitedNum < k { firstKth[visitedNum] = cur.Val } else { break } visitedNum++ if cur.Right != nil { cur = cur.Right } else { cur = nil } } } return firstKth[k-1 ] }
记录左子树节点个数,递归
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 func kthSmallest (root *TreeNode, k int ) int { left := countNum(root.Left) if left == k-1 { return root.Val } else if left > k-1 { return kthSmallest(root.Left, k) } else { return kthSmallest(root.Right, k-left-1 ) } } func countNum (root *TreeNode) int { if root != nil { left := countNum(root.Left) right := countNum(root.Right) return left+right+1 } return 0 }