最长回文子串 最长回文子串
解题思路
中心扩展算法 ,从每个位置出发,向两边扩展 ,若遇到的是回文子串,就继续扩展;若不是回文子串就结束,到下一个位置去。扩展方法:
向左扩展 ,向左寻找与当前位置相同的字符,直到遇到不等的字符为止
向右扩展 ,向右扩展,向右寻找与当前位置相同的字符,直到遇到不等的字符为止
左右双向扩展 ,同时向左右扩展,直到遇到左右字符不等为止
动态规划 法,用dp[i][j]
表示字符串s
从第i
个字符到第j
个字符是否未回文子串(true
表示是回文子串,false
表示不是回文子串)。
则状态转移方程 为dp[i][j] = dp[i+1][j-1] ^ (s[i] == s[j])
边界条件
只有一个字符时,肯定是回文子串dp[i][i] = true
只有两个字符时,只要两个字符相等就一定是回文子串dp[i][i+1] = (s[i] == s[i+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 longestPalindrome (s string ) string { len := len (s) var left, right int var maxStart, maxLen int for i := 0 ; i < len ; i++ { curLen := 1 for left = i-1 ; left >= 0 && s[left] == s[i]; left-- { curLen++ } for right = i+1 ; right < len && s[right] == s[i]; right++ { curLen++ } for left >= 0 && right < len { if s[left] != s[right] { break } left-- right++ curLen+=2 } if curLen > maxLen { maxLen = curLen maxStart = left+1 } } return s[maxStart:maxStart + maxLen] }
动态规划
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 func longestPalindrome (s string ) string { len := len (s) if len < 2 { return s } var maxStart int maxLen := 1 dp := make ([][]bool , len ) for i := 0 ; i < len ; i++ { dp[i] = make ([]bool , len ) } for j := 1 ; j < len ; j++ { for i := 0 ; i < j; i++ { if s[i] == s[j] && (j-i <= 2 || dp[i+1 ][j-1 ] == true ) { dp[i][j] = true if j-i+1 > maxLen { maxStart = i maxLen = j-i+1 } } } } return s[maxStart:maxStart+maxLen] }
合并K个排序链表 合并K个排序链表
解题思路
暴力法,根据归并 的思想,每次选取排序链表组中值最小 的节点加入到结果链表中
顺序合并 ,对于两个有序链表的合并是简单的,那么可以逐一合并各个链表,第i
次合并第i
个链表
分治合并 ,对方法2进行优化,不对其进行顺序合并,而是两两合并 。
若有k个链表,第一轮合并k/2
组链表,每一组时间代价是O(2n)
第二轮合并k/4
组链表,每一组时间代价O(4n)
以此类推,最后剩下一个链表即为结果
解题代码
暴力归并
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 46 47 48 func mergeKLists (lists []*ListNode) *ListNode { newHead := &ListNode{} rear := newHead p := make ([]*ListNode, len (lists)) for i := 0 ; i < len (lists); i++ { p[i] = lists[i] } var overNum int for overNum <= len (lists)-1 { min := p[0 ] minIndex := 0 for i := 0 ; i < len (lists); i++ { if min == nil || (p[i] != nil && p[i].Val < min.Val) { min = p[i] minIndex = i } } if min == nil { break } p[minIndex] = p[minIndex].Next if p[minIndex] == nil { overNum++ } rear.Next = min rear = rear.Next rear.Next = nil } for i := 0 ; i < len (p); i++ { if p[i] != nil { rear.Next = p[i] break } } return newHead.Next }
顺序合并
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 46 47 48 49 func mergeKLists (lists []*ListNode) *ListNode { if len (lists) == 0 { return nil } res := lists[0 ] for i := 1 ; i < len (lists); i++ { res = mergeList(res, lists[i]) } return res } func mergeList (l1, l2 *ListNode) *ListNode { newHead := &ListNode{} rear := newHead p, q := l1, l2 for p!= nil && q != nil { if p.Val < q.Val { rear.Next = p p = p.Next rear = rear.Next rear.Next = nil } else { rear.Next = q q = q.Next rear = rear.Next rear.Next = nil } } if p != nil { rear.Next = p } if q != nil { rear.Next = q } return newHead.Next }
分治合并
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 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 func mergeKLists (lists []*ListNode) *ListNode { k := len (lists) if k == 0 { return nil } for k > 1 { newLists := make ([]*ListNode, 0 ) k = 0 for i := 0 ; i < len (lists); i+=2 { if i != len (lists)-1 { newLists = append (newLists, mergeList(lists[i], lists[i+1 ])) k++ } else { newLists = append (newLists, lists[i]) k++ } } lists = newLists } return lists[0 ] } func mergeList (l1, l2 *ListNode) *ListNode { newHead := &ListNode{} rear := newHead p, q := l1, l2 for p!= nil && q != nil { if p.Val < q.Val { rear.Next = p p = p.Next rear = rear.Next rear.Next = nil } else { rear.Next = q q = q.Next rear = rear.Next rear.Next = nil } } if p != nil { rear.Next = p } if q != nil { rear.Next = q } return newHead.Next }
合并区间 合并区间
解题思路 首先对区间的左端点进行排序 ,那么在排完序的列表中,可以合并的区间一定是连续的 。将第一个区间加入结果res
中,并且按顺序考虑每个区间:
若当前区间与结果集的最后一个区间不相交,那么将当前区间加入到结果集中
若当前区间与结果集的最后一个区间相交,那么进一步考虑若当前的右端点在结果集的最后一个区间的右端点的右侧,则更新结果集中最后一个区间的右端点
解题代码 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 ints [][]int func merge (intervals [][]int ) [][]int { if len (intervals) == 0 { return nil } ints := ints(intervals) sort.Sort(ints) intervals = [][]int (ints) res := [][]int {intervals[0 ]} for i := 1 ; i < len (intervals); i++ { if intervals[i][0 ] > res[len (res)-1 ][1 ] { res = append (res, intervals[i]) } else { if intervals[i][1 ] > res[len (res)-1 ][1 ] { res[len (res)-1 ][1 ] = intervals[i][1 ] } } } return res } func (this ints) Len () int { return len (this) } func (this ints) Less (i, j int ) bool { if this[i][0 ] < this[j][0 ] { return true } else { return false } } func (this ints) Swap (i, j int ) { this[i], this[j] = this[j], this[i] }
二叉树的最大高读 二叉树的最大深度
解题思路 基于二叉树的后续遍历,首先得到左子树高度left
,右子树高度right
,二叉树高度为1 + max(left, right)
解题代码 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 func maxDepth (root *TreeNode) int { var postorder func (root *TreeNode) int postorder = func (root *TreeNode) int { if root != nil { left := postorder(root.Left) right := postorder(root.Right) return 1 + max(left, right) } else { return 0 } } return postorder(root) } func max (n1, n2 int ) int { if n1 > n2 { return n1 } else { return n2 } }
平衡二叉树 平衡二叉树
解题思路 若left
为左子树高度,right
为右子树高度,若|left - right| <= 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 43 44 45 46 47 func isBalanced (root *TreeNode) bool { if root != nil { left := height(root.Left) right := height(root.Right) return abs(left-right) <= 1 && isBalanced(root.Left) && isBalanced(root.Right) } else { return true } } func height (root *TreeNode) int { if root != nil { left := height(root.Left) right := height(root.Right) return 1 + max(left, right) } else { return 0 } } func max (n1, n2 int ) int { if n1 > n2 { return n1 } else { return n2 } } func abs (n int ) int { if n >= 0 { return n } else { return -n } }