常考算法

208 阅读2分钟
package main

import (
	"container/list"
	"fmt"
	"math"
	"sort"
	"strings"
	"testing"
)

func TestReadFromFile(t *testing.T) {
	fmt.Println("productExceptSelf = ", productExceptSelf([]int{1, 2, 3, 4}))

}

//----------struct---------
type ListNode struct {
	Val  int
	Next *ListNode
}

type TreeNode struct {
	Val   int
	Left  *TreeNode
	Right *TreeNode
}

//----------tools---------------
func min(a, b int) int {
	if a > b {
		return b
	}
	return a
}

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

func swap(nums []int, i, j int) {
	nums[i], nums[j] = nums[j], nums[i]
}

//heapify 从给定的i向下堆化为小顶堆
func heapify(a []int, i int) {
	n := len(a) - 1
	for {
		minPos := i
		if i*2 <= n && a[i*2] < a[minPos] {
			minPos = i * 2
		}
		if i*2+1 <= n && a[i*2+1] < a[minPos] {
			minPos = i*2 + 1
		}
		if minPos == i {
			break
		}
		a[minPos], a[i] = a[i], a[minPos]
		i = minPos
	}
}

// 自顶向下调整,用于调整堆顶
func siftDown(nums []int, index int) {
	numsLen := len(nums)
	minIndex := index
	for {
		left, right := 2*index+1, 2*index+2
		if left < numsLen && nums[left] < nums[minIndex] {
			minIndex = left
		}
		if right < numsLen && nums[right] < nums[minIndex] {
			minIndex = right
		}
		if minIndex == index {
			break
		}
		swap(nums, index, minIndex)
		index = minIndex
	}
}

// 自底向上调整,用于调整整个堆
func siftUp(nums []int) {
	numsLen := len(nums)
	for parent := numsLen/2 - 1; parent >= 0; parent-- {
		minIndex := parent
		left, right := 2*parent+1, 2*parent+2
		if left < numsLen && nums[left] < nums[minIndex] {
			minIndex = left
		}
		if right < numsLen && nums[right] < nums[minIndex] {
			minIndex = right
		}
		if parent != minIndex {
			swap(nums, parent, minIndex)
		}
	}
}

//-----------------------------------------
//两数之和
func twoSum(nums []int, target int) []int {
	m := map[int]int{}
	for i, v := range nums {
		if k, ok := m[target-v]; ok {
			return []int{k, i}
		}
		m[v] = i
	}
	return nil
}

//链表相加
func addTwoNumbers(l1 *ListNode, l2 *ListNode) *ListNode {
	list := &ListNode{0, nil}
	result := list
	tmp := 0
	for l1 != nil || l2 != nil || tmp != 0 {
		if l1 != nil {
			tmp += l1.Val
			l1 = l1.Next
		}
		if l2 != nil {
			tmp += l2.Val
			l2 = l2.Next
		}
		list.Next = &ListNode{tmp % 10, nil}
		tmp = tmp / 10
		list = list.Next
	}
	return result.Next
}

//反转链表
func reverseList(head *ListNode) *ListNode {
	prev, cur := new(ListNode), head

	for cur != nil {
		cur.Next, prev, cur = prev, cur, cur.Next
	}

	return prev
}

//两两反转链表
func swapPairs(head *ListNode) *ListNode {
	dummy := &ListNode{
		Val:  -1,
		Next: head,
	}
	preNode := dummy

	for head != nil && head.Next != nil {
		first := head
		second := head.Next
		preNode.Next, second.Next, first.Next = second, first, second.Next
		preNode = first
		head = first.Next
	}
	return dummy.Next
}

//反转部分链表
func reverseBetween(head *ListNode, m int, n int) *ListNode {
	// 关键点是m的前一个节点
	dummy := &ListNode{
		Next: head,
	}
	prem := dummy
	for i := 1; i <= m-1; i++ {
		prem = prem.Next
	}

	// m和n区间内反转【跟反转链表一样】
	prev, cur := new(ListNode), head

	for i := m; i <= n; i++ {
		cur.Next, prev, cur = prev, cur, cur.Next
	}

	// prem.Next为m节点,原始m节点应该指向n+1节点
	prem.Next.Next = cur
	// prem指向pre(反转之后的头节点)
	prem.Next = prev

	return dummy.Next
}

//链表是否有环
func hasCycle(head *ListNode) bool {
	fast, slow := head, head
	for fast != nil && fast.Next != nil {
		fast = fast.Next.Next
		slow = slow.Next
		if fast == slow {
			return true
		}
	}

	return false
}

//链表相交点
func getIntersectionNode(headA, headB *ListNode) *ListNode {
	curA, curB := headA, headB
	for curA != curB {
		if curA == nil {
			curA = headB
		} else {
			curA = curA.Next
		}

		if curB == nil {
			curB = headA
		} else {
			curB = curB.Next
		}
	}
	return curA
}

//合并两有序链表
func mergeTwoLists(l1 *ListNode, l2 *ListNode) *ListNode {
	prehead := &ListNode{}
	result := prehead
	for l1 != nil && l2 != nil {
		if l1.Val < l2.Val {
			prehead.Next = l1
			l1 = l1.Next
		} else {
			prehead.Next = l2
			l2 = l2.Next
		}
		prehead = prehead.Next
	}
	if l1 != nil {
		prehead.Next = l1
	}
	if l2 != nil {
		prehead.Next = l2
	}
	return result.Next
}

//合并K个有序链表【done】
func mergeKLists(lists []*ListNode) *ListNode {
	length := len(lists)

	switch length {
	case 0:
		return nil
	case 1:
		return lists[0]
	}

	first := mergeKLists(lists[:length/2])
	second := mergeKLists(lists[length/2:])
	return mergeTwoLists(first, second)
}

//删除倒数第N节点
func removeNthFromEnd(head *ListNode, n int) *ListNode {
	result := &ListNode{}
	result.Next = head
	pre, cur := new(ListNode), result
	i := 1
	for head != nil {
		if i >= n {
			pre = cur
			cur = cur.Next
		}
		head = head.Next
		i++
	}
	pre.Next = pre.Next.Next
	return result.Next
}

//判断回文链表
func isPalindrome(head *ListNode) bool {
	if head == nil {
		return true
	}
	var res []*ListNode
	for head != nil {
		res = append(res, head)
		head = head.Next
	}
	left := 0
	right := len(res) - 1
	for left < right {
		if res[left].Val != res[right].Val {
			return false
		}
		left++
		right--
	}
	return true
}

//反转单词顺序
func reverseWords(s string) string {
	strList := strings.Split(s, " ")
	var res []string
	for i := len(strList) - 1; i >= 0; i-- {
		str := strings.TrimSpace(strList[i])
		if len(str) > 0 {
			res = append(res, strList[i])
		}
	}
	return strings.Join(res, " ")
}

//最长公共前缀
func longestCommonPrefix(strs []string) string {
	if len(strs) < 1 {
		return ""
	}
	prefix := strs[0]
	for _, k := range strs {
		for strings.Index(k, prefix) != 0 {
			if len(prefix) == 0 {
				return ""
			}
			prefix = prefix[:len(prefix)-1]
		}
	}
	return prefix
}

//反转数字序列
func rotate(nums []int, k int) []int {
	reverse(nums)
	reverse(nums[:k%len(nums)])
	reverse(nums[k%len(nums):])
	return nums
}

func reverse(arr []int) {
	for i := 0; i < len(arr)/2; i++ {
		arr[i], arr[len(arr)-i-1] = arr[len(arr)-i-1], arr[i]
	}
}

//取交集
func intersect(nums1 []int, nums2 []int) []int {
	i, j, k := 0, 0, 0
	sort.Ints(nums1)
	sort.Ints(nums2)
	for i < len(nums1) && j < len(nums2) {
		if nums1[i] > nums2[j] {
			j++
		} else if nums1[i] < nums2[j] {
			i++
		} else {
			nums1[k] = nums1[i]
			i++
			j++
			k++
		}
	}
	return nums1[:k]
}

//删除指定元素
func removeElement(nums []int, val int) []int {
	for i := 0; i < len(nums); { //2, 2, 3, 4, 2, 6, 7
		if nums[i] == val {
			nums = append(nums[:i], nums[i+1:]...)
		} else {
			i++
		}
	}
	return nums
}

//去除已排序数组重复数字,删除重复元素
func removeDuplicates(nums []int) int {
	for i := 0; i+1 < len(nums); {
		if nums[i] == nums[i+1] {
			nums = append(nums[:i], nums[i+1:]...)
		} else {
			i++
		}
	}
	return len(nums)
}

//[1,2,3,4] => [24,12,8,6]
func productExceptSelf(nums []int) []int {
	ans := make([]int, len(nums))
	k := 1
	for i := 0; i < len(nums); i++ {
		ans[i] = k
		k = k * nums[i]
	}
	k = 1
	fmt.Println("ans = ", ans)
	for i := len(nums) - 1; i >= 0; i-- {
		ans[i] *= k
		k = k * nums[i]
	}
	return ans
}

//下一个排列
func nextPermutation(nums []int) {
	if len(nums) <= 1 {
		return
	}

	i, j, k := len(nums)-2, len(nums)-1, len(nums)-1

	// find: A[i]<A[j]
	for i >= 0 && nums[i] >= nums[j] {
		i--
		j--
	}

	if i >= 0 { // 不是最后一个排列
		// find: A[i]<A[k]
		for nums[i] >= nums[k] {
			k--
		}
		// swap A[i], A[k]
		nums[i], nums[k] = nums[k], nums[i]
	}

	// reverse A[j:end]
	for i, j := j, len(nums)-1; i < j; i, j = i+1, j-1 {
		nums[i], nums[j] = nums[j], nums[i]
	}
}

//股票买卖-持有1股,买卖无数次
func maxProfit(prices []int) int { //7, 1, 5, 3, 6, 4
	sum := 0
	for i := 1; i < len(prices); i++ {
		if prices[i]-prices[i-1] > 0 {
			sum += prices[i] - prices[i-1]
		}
	}
	return sum
}

//股票买卖-持有1股,买卖1次
func maxProfitOnce(prices []int) int {
	var min = math.MaxInt32
	var maxDiff int

	for i := 0; i < len(prices); i++ {
		if min > prices[i] {
			min = prices[i]
		}
		diff := prices[i] - min
		if maxDiff < diff {
			maxDiff = diff
		}
	}

	return maxDiff
}

//连续子数组的最大和
//输入: [-2,1,-3,4,-1,2,1,-5,-4,-2]
//解释: 连续子数组 [4,-1,2,1] 的和最大,为 6
func maxSubArray(nums []int) int {
	max := math.MinInt32
	tmp := 0
	for _, v := range nums {
		if tmp > 0 {
			tmp += v
		} else {
			tmp = v
		}
		if max < tmp {
			max = tmp
		}
	}
	return max
}

//最大连续子序列和
func maxSubArrayDP(nums []int) int {
	if len(nums) < 1 {
		return 0
	}
	dp := make([]int, len(nums))
	result := nums[0] //max值
	dp[0] = nums[0]
	for i := 1; i < len(nums); i++ {
		dp[i] = max(dp[i-1]+nums[i], nums[i])
		result = max(dp[i], result)
	}
	return result
}

//乘积最大子数组
func maxProduct(nums []int) int {
	maxDP := make([]int, len(nums))
	minDP := make([]int, len(nums))
	maxDP[0] = nums[0]
	minDP[0] = nums[0]
	max := nums[0]
	for i := 1; i < len(nums); i++ {
		maxDP[i], minDP[i] = numCompare(minDP[i-1]*nums[i], maxDP[i-1]*nums[i], nums[i])
		if max < maxDP[i] {
			max = maxDP[i]
		}
	}
	return max
}

func numCompare(a, b, c int) (max, min int) {
	s := []int{a, b, c}
	sort.Ints(s)
	return s[2], s[0]
}

//输入: [10,9,2,5,3,7,101,18] 输出: 4
//解释: 最长的上升子序列是 [2,3,7,101],它的长度是 4。
func lengthOfLIS(nums []int) int {
	if len(nums) < 1 {
		return 0
	}
	dp := make([]int, len(nums))
	result := 1
	for i := 0; i < len(nums); i++ {
		dp[i] = 1
		for j := 0; j < i; j++ {
			//这行代码就是上文中那个 等等等等
			if nums[j] < nums[i] {
				dp[i] = max(dp[j]+1, dp[i])
			}
		}
		result = max(result, dp[i])
	}
	return result
}

//寻找奇点(山峰)
func findPeakElement(nums []int) int { //4, 5, 6, 7, 0, 1, 2
	left, right := 0, len(nums)-1
	for left < right {
		mid := left + (right-left)/2
		if nums[mid] > nums[mid+1] {
			right = mid
		} else {
			left = mid + 1
		}
	}
	return left
}

//旋转数组寻找最小数
func findMin(nums []int) int {
	left, right := 0, len(nums)-1
	for left < right {
		mid := left + (right-left)/2
		if nums[mid] > nums[right] {
			left = mid + 1
		} else {
			right = mid
		}
	}
	return nums[left]
}

//查找第一个值等于给定值的元素
func firstNumIndex(array []int, n int) int {
	low, high := 0, len(array)
	for low <= high {
		mid := low + (high-low)/2
		if array[mid] < n {
			low = mid + 1
		} else if array[mid] > n {
			high = mid - 1
		} else {
			if mid == 0 || array[mid-1] != n {
				return mid
			} else {
				high = mid - 1
			}
		}
	}
	return -1
}

//查找第一个大于等于给定值得元素
func firstBigNumIndex(array []int, n int) int {
	low, high := 0, len(array)
	for low <= high {
		mid := low + (high-low)/2
		if array[mid] >= n {
			if mid == 0 || array[mid-1] < n {
				return mid
			} else {
				high = mid - 1
			}
		} else {
			low = mid + 1
		}
	}
	return -1
}

//最大不重复子序列长度
func MaxSubStringLength(s string) int { //abcabcbbccjkla
	n, ans := len(s), 0
	m := make(map[byte]int, 0)

	for end, start := 0, 0; end < n; end++ {
		if v, ok := m[s[end]]; ok {
			start = int(math.Max(float64(v), float64(start)))
		}
		ans = int(math.Max(float64(ans), float64(end-start)))
		m[s[end]] = end
	}

	return ans
}

//基数在前,偶数在后,扩展字符串大小写字母前后部分,顺序不变
func sortArrayByParity(A []int) []int {
	j := 0
	for i := range A {
		if A[i]%2 == 0 {
			A[j], A[i] = A[i], A[j]
			j++
		}
	}
	return A
}

//快速排序
func quickSort(arr []int) {
	start, end := 0, len(arr)-1
	quickCore(arr, start, end)
}

func quickCore(arr []int, start int, end int) {
	i, j := start, end
	key := arr[start] //基数任意一个
	for i <= j {
		for arr[i] < key {
			i++
		}
		for arr[j] > key {
			j--
		}
		if i <= j {
			arr[i], arr[j] = arr[j], arr[i]
			i++
			j--
		}
	}

	if start < j {
		quickCore(arr, start, j)
	}
	if end > i {
		quickCore(arr, i, end)
	}
}

//二叉树最小公共祖先
func lowestCommonAncestor(root, p, q *TreeNode) *TreeNode {
	if root == nil || root == p || root == q {
		return root
	}
	l := lowestCommonAncestor(root.Left, p, q)
	r := lowestCommonAncestor(root.Right, p, q)
	if l == nil {
		return r
	}
	if r == nil {
		return l
	}
	return root
}

//前序中序构建二叉树
func buildTree(preorder []int, inorder []int) *TreeNode {
	for k := range inorder {
		if inorder[k] == preorder[0] { //中序遍历 root (index=k)
			return &TreeNode{
				Val: preorder[0],
				//Val: inorder[root],
				Left:  buildTree(preorder[1:k+1], inorder[0:k]),
				Right: buildTree(preorder[k+1:], inorder[k+1:]),
			}
		}
	}
	return nil
}

//是否平衡二叉树
func isValidBST(root *TreeNode) bool {
	if root == nil {
		return true
	}
	return isBST(root, math.MinInt64, math.MaxInt64)
}

func isBST(root *TreeNode, min, max int) bool {
	if root == nil {
		return true
	}
	if min >= root.Val || max <= root.Val {
		return false
	}
	return isBST(root.Left, min, root.Val) && isBST(root.Right, root.Val, max)
}

//BFS
func levelOrder(root *TreeNode) [][]int {
	var result [][]int
	if root == nil {
		return result
	}
	// 定义一个双向队列
	queue := list.New()
	// 插入根结点完成初始化
	queue.PushFront(root)
	// 进行广度搜索
	for queue.Len() > 0 {
		var current []int
		listLength := queue.Len()
		for i := 0; i < listLength; i++ {
			// 消耗尾部
			// queue.Remove(queue.Back()).(*TreeNode):移除最后一个元素并将其转化为TreeNode类型
			node := queue.Remove(queue.Back()).(*TreeNode)
			current = append(current, node.Val)
			if node.Left != nil {
				//插入头部
				queue.PushFront(node.Left)
			}
			if node.Right != nil {
				queue.PushFront(node.Right)
			}
		}
		result = append(result, current)
	}
	return result
}

//对称(镜像)二叉树
func isSymmetric(root *TreeNode) bool {
	if root == nil {
		return true
	}
	return dfsIsSymmetric(root.Left, root.Right)
}
func dfsIsSymmetric(a, b *TreeNode) bool {
	if a == nil && b == nil {
		return true
	}
	if (a == nil && b != nil) || (a != nil && b == nil) || (a.Val != b.Val) {
		return false
	}
	return dfsIsSymmetric(a.Left, b.Right) && dfsIsSymmetric(a.Right, b.Left)
}

//---两栈实现队列----
type MyQueue struct {
	input  []int
	output []int
}

/** Initialize your data structure here. */
func Constructor() MyQueue {
	return MyQueue{}
}

/** Push element x to the back of queue. */
func (this *MyQueue) Push(x int) {
	this.input = append(this.input, x)
}

/** Removes the element from in front of queue and returns that element. */
func (this *MyQueue) Pop() int {
	this.Peek()
	e := this.output[len(this.output)-1]
	this.output = this.output[:len(this.output)-1]
	return e
}

/** Get the front element. */
func (this *MyQueue) Peek() int {
	if len(this.output) == 0 {
		for len(this.input) > 0 {
			this.output = append(this.output, this.input[len(this.input)-1])
			this.input = this.input[:len(this.input)-1]
		}
	}
	return this.output[len(this.output)-1]
}

/** Returns whether the queue is empty. */
func (this *MyQueue) Empty() bool {
	if len(this.input) == 0 && len(this.output) == 0 {
		return true
	}
	return false
}

//TODO
//括号生成

//数组中重复的数字

//------------end---------------