二叉搜索树
所谓的二叉搜索树(BST),就是满足二叉树中每个节点大于左子树小于右子树的二叉树,而二叉树搜索树的插入对比它的这一特征,插入就能够很好的解决,判断当前节点是否为空,为空直接插入数字并返回,不为空,与该节点的val进行对比,进行循环递归,直到该节点的值大于val并且该节点左子树为空插入val,或者该节点的值小于val并且右子树为空插入val。
/** * Definition for a binary tree node. * type TreeNode struct { * Val int * Left *TreeNode * Right *TreeNode * } */ func insertIntoBST(root *TreeNode, val int) *TreeNode { if root == nil { return &TreeNode{Val: val} } p := root for p != nil{ if p.Val < val { if p.Right != nil { p = p.Right }else { p.Right = &TreeNode{Val: val} break } }else { if p.Left != nil { p = p.Left }else { p.Left = &TreeNode{Val: val} break } } } return root }
两数相加
题目描述两个非空链表相加,由于是逆序存贮,所以只需要用一个变量存贮进位就可以了,当两个链表都为空并且进位也为0的时候,表示两个链表相加完毕。最后返回头节点。
/** * Definition for singly-linked list. * type ListNode struct { * Val int * Next *ListNode * } */ func addTwoNumbers(l1 *ListNode, l2 *ListNode) *ListNode { return addTwoNumber(l1, l2, 0) } func addTwoNumber(l1 *ListNode, l2 *ListNode, add int) *ListNode{ if l1 == nil && l2 == nil && add == 0 { return nil } if l1 != nil { add += l1.Val l1 = l1.Next } if l2 != nil { add += l2.Val l2 = l2.Next } node := ListNode{ Val: add % 10, Next: addTwoNumber(l1, l2, add / 10), } return &node }
无重复最长子串
给定一个字串,求出最长不重复的字串。模拟一下求解最长不重复子串的过程,将第一个字符存入map中,在以第一个字符为起点循环判断存入字符,当一个字符第二次出现时,当前位置减去起点的位置,这中间就是无重复字串的长度,给定一个变量ans存入长度最大值。当前这一个无重复字串就相当于一个滑动框,我们起点+1,更换起点,滑动框右边在进行判断查找,重复以上操作,找到一个无重复字串的最大值。
func lengthOfLongestSubstring(s string) int { mp := map[byte]int{} rk := -1 ans := 0 for i := 0; i < len(s); i++ { if i != 0 { delete(mp, s[i-1]) } for rk+1 < len(s) && mp[s[rk+1]]==0 { mp[s[rk+1]]++ rk++ } ans = max(ans, rk - i +1) } return ans } func max(a, b int) int { if a <= b { return b }else { return a } }
四数之和
给定一个一维数组,求出这个数组之中满足4个数之和等于target的数组集合,最常想到的方法是先对数组排序,在进行四重循环,得到满足条件的数组,在对数组进行去从。我在这里是写的一个check函数进行去从,也可以在循环中添加条件,即同一重循环中,在满足条件后,当num[i]==num[i-1]时 continue。
var ans [][]int func fourSum(nums []int, target int) [][]int { ans = [][]int{} sort.Ints(nums) for i := 0; i < len(nums); i++ { for j := i+1; j < len(nums); j++ { for k := j+1; k < len(nums); k++ { for l := k+1; l < len(nums); l++ { if nums[i] + nums[j] + nums[k] + nums[l] > target { break } if nums[i] + nums[j] + nums[k] + nums[l] == target { if check([]int{nums[i], nums[j], nums[k], nums[l]}){ ans = append(ans, []int{nums[i], nums[j], nums[k], nums[l]}) } } } } } } return ans } func check(nums []int) bool{ flag := 0 for i := 0; i < len(ans); i++ { for j :=0; j < len(nums); j++{ if ans[i][j] == nums[j] { flag = 1 }else { flag = 0 break } } if flag == 1 { return false } } return true }
当然这种算法的复杂度是O(n4)。在这个基础上我们可以使用双指针的方法,枚举i,j 在进行双指针判断num[i]+num[j]+num[left]+num[right]==target 得到满足条件的数组。在这基础上我们可以在同一重循环中在进行优化,在i这层循环中,如果num[i]+num[n-1]+num[n-2]+num[n-3]<target 可以直接进行下一次循环,同理在j这一层循环中,如果num[i]+num[n-1]+num[n-2]+num[j]<target,可以直接进行下一次循环。进而时间复杂度优化为O(n3)
func fourSum1(nums []int, target int) [][]int { sort.Ints(nums) ans = [][]int{} n := len(nums) for i := 0; i < n-3 && nums[i]+nums[i+1]+nums[i+2]+nums[i+3] <= target; i++ { if i > 0 && nums[i] == nums[i-1] || nums[i]+nums[n-1]+nums[n-2]+nums[n-3] < target { continue } for j := i+1; j < n-2 && nums[j]+nums[j+1]+nums[j+2]+nums[i] <= target; j++ { if j > i+1 && nums[j] == nums[j-1] || nums[i]+nums[n-1]+nums[n-2]+nums[j] < target { continue } for left, right := j+1, n-1; left < right; { if nums[i] + nums[j] + nums[left] + nums[right] == target { ans = append(ans, []int{nums[i], nums[j], nums[left], nums[right]}) for ;nums[left]==nums[left+1];left++ { } for ;nums[right]==nums[right-1];right-- { } left++ right-- }else if nums[i] + nums[j] + nums[left] + nums[right] < target { left++ }else { right-- } } } } return ans }
三数之和
同四数之和,进行一重循环加上双指针进行优化,从而在O(n2)的复杂度上得到答案
func threeSum(nums []int) [][]int { ans := [][]int{} sort.Ints(nums) n := len(nums) for i:=0; i < n-2 && nums[i]+nums[i+1]+nums[i+2] <= 0; i++ { if i > 0 && nums[i] == nums[i-1] || nums[i]+nums[n-1]+nums[n-2] < 0 { continue } for left, right := i+1, n-1; left < right; { if sum := nums[i]+nums[left]+nums[right]; sum == 0 { ans = append(ans, []int{nums[i], nums[left], nums[right]}) for left++; left < right && nums[left]==nums[left-1]; left++ { } for right--; left < right && nums[right] == nums[right+1]; right--{ } }else if sum < 0 { left++ }else { right-- } } } return ans }