//螺旋矩阵
func spiralOrder(matrix [][]int) []int {
//首先二维矩阵的行列不为0
if len(matrix) == 0 || len(matrix[0]) == 0 {
return []int{}
}
//二维矩阵的行列数,常量
rows, columns := len(matrix), len(matrix[0])
//二维数组标记每个点是否被访问过
visited := make([][]bool, rows)
for i := 0; i < rows; i++ {
visited[i] = make([]bool, columns)
}
var (
//创建一维数组生成的数据
total = rows * columns
order = make([]int, total)
//初始位置坐标
row, column = 0, 0
//四个坐标方向的元素数组
directions = [][]int{[]int{0, 1}, []int{1, 0}, []int{0, -1}, []int{-1, 0}}
//坐标方向index
directionIndex = 0
)
for i := 0; i < total; i++ {
order[i] = matrix[row][column]
visited[row][column] = true
//生成下个位置点走向
nextRow, nextColumn := row + directions[directionIndex][0], column + directions[directionIndex][1]
if nextRow < 0 || nextRow >= rows || nextColumn < 0 || nextColumn >= columns || visited[nextRow][nextColumn] {
directionIndex = (directionIndex + 1) % 4
}
//产生下一个位置坐标
row += directions[directionIndex][0]
column += directions[directionIndex][1]
}
return order
}
//链表求和 +2
func addTwoNumbers(l1, l2 *ListNode) (head *ListNode) {
tail := &ListNode{}
var carry int
for l1 != nil || l2 != nil {
n1, n2 := 0, 0
if l1 != nil {
n1 = l1.Val
l1 = l1.Next
}
if l2 != nil {
n2 = l2.Val
l2 = l2.Next
}
sum := n1 + n2 + carry
sum, carry = sum%10, sum/10
if head == nil {
head = &ListNode{Val: sum}
tail = head
} else {
tail.Next = &ListNode{Val: sum}
tail = tail.Next
}
}
if carry > 0 {
tail.Next = &ListNode{Val: carry}
}
return
}
//复制带随机指针的链表 +2
/**
* Definition for a Node.
* type Node struct {
* Val int
* Next *Node
* Random *Node
* }
*/
func copyRandomList(head *Node) *Node {
curr := head
m := make(map[uintptr]*Node)
for curr != nil {
m[uintptr(unsafe.Pointer(curr))] = &Node{Val: curr.Val}
curr = curr.Next
}
curr = head
for curr != nil {
node := m[uintptr(unsafe.Pointer(curr))]
node.Next = m[uintptr(unsafe.Pointer(curr.Next))]
node.Random = m[uintptr(unsafe.Pointer(curr.Random))]
curr = curr.Next
}
return m[uintptr(unsafe.Pointer(head))]
}
// 计算岛屿数量 +2
func numIslands(grid [][]byte) int {
var count int
n, m := len(grid), len(grid[0])
for i := 0; i < n; i++ {
for j := 0; j < m; j++ {
if grid[i][j] == '1' {
dfs(grid, i, j)
count ++
}
}
}
return count
}
// 从一个陆地节点,开始 深度优先探索, 返回一片岛屿
// 深度优先探索
func dfs(grid [][]byte, x int, y int) {
for x >= 0 && y >= 0 && x < len(grid) && y < len(grid[x]) && grid[x][y] == '1' {
grid[x][y] = '0'
dfs(grid, x, y + 1)
dfs(grid, x, y - 1)
dfs(grid, x + 1, y)
dfs(grid, x - 1, y)
}
}
// <计算岛屿周长>
//M1: 迭代 逻辑上更容易理解 +2
// 时间复杂度 O(N3)
// 空间复杂度
type pair struct {x, y int}
var dir4 []pair{{0, 1}, {0, -1}, {1, 0}, {-1, 0}}
func islandPerimeter(grid [][]int) (ans int) {
n, m := len(grid), len(grid[0])
for i, row := range grid {
for j, v := row {
if v == 1 {
for _, p := range dir4 {
if x, y := i+p.x, j+p.y; x < 0 || y < 0 || x >= n || y >= m || grid[x][y] == 0 {
ans++
}
}
}
}
}
return
}
//M2: 深度优先探索 +2
type pair struct{ x, y int }
var dir4 = []pair{{-1, 0}, {1, 0}, {0, -1}, {0, 1}}
func islandPerimeter(grid [][]int) (ans int) {
n, m := len(grid), len(grid[0])
var dfs func(x, y int)
dfs = func(x, y int) {
if x < 0 || y < 0 || x >= n || y >= m || grid[x][y] == 0 {
ans++
return
}
if grid[x][y] == 2 {
return
}
grid[x][y] = 2
for _, p := range dir4 {
// fix: 锚点四周岛屿扫描,锚点(x,y)位置点不能变
// x, y = x+p.x, y+p.y
// dfs(x, y)
dfs(x+p.x, y+p.y)
}
}
for i, row := range grid {
for j, v := range row {
if v == 1 {
dfs(i, j)
}
}
}
return
}
//<最长回文字段>
// M1: 看不懂..// M2: 中心扩展算法
func longestPalindrome(s string) string {
if s == "" {
return ""
}
start, end := 0, 0
for i := 0; i < len(s); i++ {
// 依次以i为中心,向两侧扩展,寻找最大回文
left1, right1 := expandAroundCenter(s, i, i)
// 依次以(i,i+1)为中心,向两侧扩展,寻找最大回文
left2, right2 := expandAroundCenter(s, i, i + 1)
// 取 每次i回文长度最长的 起始点
if right1 - left1 > end - start {
start, end = left1, right1
}
// 取 每次(i,i+1)回文长度最长的 起始点
if right2 - left2 > end - start {
start, end = left2, right2
}
}
//返回最长回文字段
return s[start:end+1]
}
func expandAroundCenter(s string, left, right int) (int, int) {
// for循环,没有初始化值, 两侧值相等,则继续向外扩
for ; left >= 0 && right < len(s) && s[left] == s[right]; left, right = left-1 , right+1 { }
// s[left]不等于 s[right]; 那么返回 上一对相等的left和right
return left + 1, right - 1
}
// LRU缓存机制 [ 先忽略 ]
// 翻转字符串里的单词
func reverseWords(s string) string {
if len(s) == 0 {
return s
}
s = PreProcess(s)
slice := strings.Split(s, " ")
l := len(slice) - 1
var i int
for i < l {
slice[i], slice[l] = slice[l], slice[i]
l--
i++
}
return strings.Join(slice, " ")
}
//处理字符串中连续的空格
func PreProcess(s string) string {
l := len(s)
var res []byte
flag := 1
//处理尾部连续空格
for l > 0 && s[l - 1] == ' ' {
l--
}
for i := 0; i < l; i++ {
if s[i] != ' ' {
res = append(res, s[i])
flag = 0
}
if s[i] == ' ' && flag == 0 {
res = append(res, s[i])
flag = 1
}
}
return string(res)
}
// 翻转二叉树
/**
* Definition for a binary tree node.
* type TreeNode struct {
* Val int
* Left *TreeNode
* Right *TreeNode
* }
*/
func invertTree(root *TreeNode) *TreeNode {
if root == nil {
return nil
}
left := invertTree(root.Left)
right := invertTree(root.Right)
root.Left = right
root.Right = left
return root
}
// 二叉树最大深度
// m1: 深度优先搜索
func maxDepth(root *TreeNode) int {
if root == nil {
return 0
}
return max(maxDepth(root.Left), maxDepth(root.Right)) + 1
}
func max(a, b int) int {
if a > b {
return a
}
return b
}
// 验证二叉查找树
// m1: 递归
func isValidBST(root *TreeNode) bool {
return helper(root, math.MinInt64, math.MaxInt64)
}
func helper(root *TreeNode, lower, upper int) bool {
if root == nil {
return true
}
if root.Val <= lower || root.Val >= upper {
return false
}
return helper(root.Left, lower, root.Val) && helper(root.Right, root.Val, upper)
}
// m2: 中序遍历 (难于理解)
// 中序遍历是二叉树的一种遍历方式,它先遍历左子树,再遍历根节点,最后遍历右子树。
// 而我们二叉搜索树保证了左子树的节点的值均小于根节点的值,根节点的值均小于右子树的值,因此中序遍历以后得到的序列一定是升序序列。
func isValidBST(root *TreeNode) bool {
stack := []*TreeNode{}
inorder := math.MinInt64
for len(stack) > 0 || root != nil {
// 从根节点开始,左树节点依次入栈
for root != nil {
stack = append(stack, root)
root = root.Left
}
// 栈顶出栈 (即左树页子节点)
root = stack[len(stack)-1]
stack = stack[:len(stack)-1]
// 初始最小值为 math.MinInt64 (边界值)
if root.Val <= inorder {
return false
}
// inorder即为中序遍历到的节点
inorder = root.Val
//
root = root.Right
}
return true
}
// 路径总和是否为sum
// m2: 递归
func hasPathSum(root *TreeNode, sum int) bool {
if root == nil {
return false
}
if root.Left == nil && root.Right == nil {
return sum == root.Val
}
return hasPathSum(root.Left, sum - root.Val) || hasPathSum(root.Right, sum - root.Val)
}
//二叉查找树 (Binary Search Tree)
// 查找
func (this *TreeNode) Find(v interface{}) *TreeNode {
p := this
for p != nil {
if p.Val == v {
return p
} else if v > p.Val {
p = p.right
} else {
p = p.left
}
}
return nil
}
// 插入
// 方法:
// 如果要插入的数据比节点的数据大,并且节点的右子树为空,就将新数据直接插到右子节点的位置;
// 如果不为空,就再递归遍历右子树,查找插入位置。同理,如果要插入的数据比节点数值小,并且节点的左子树为空,就将新数据插入到左子节点的位置;
// 如果不为空,就再递归遍历左子树,查找插入位置。
func (this *TreeNode) Insert(v interface{}) bool {
p := this
for p != nil {
if p.Val == v {
return false
} else if v > p.Val {
if p.right == nil {
p.right = &TreeNode{Val: v}
break
}
p = p.right
} else {
if p.left == nil {
p.left = &TreeNode{Val: v}
break
}
p = p.left
}
}
return true
}
// 构建二叉树 (TODO)
func buildTree(preorder []int, inorder []int) *TreeNode {
if len(preorder) == 0 {
return nil
}
root := &TreeNode{preorder[0], nil, nil}
i := 0
for ; i < len(inorder); i++ {
if inorder[i] == preorder[0] {
break
}
}
root.Left = buildTree(preorder[1:len(inorder[:i])+1], inorder[:i])
root.Right = buildTree(preorder[len(inorder[:i])+1:], inorder[i+1:])
return root
}
//三数之和
func threeSum(nums []int) (ans [][]int) {
sort.Ints(nums)
n := len(nums)
// 枚举 i
for i := 0; i < n; i++ {
if i > 0 && nums[i] == nums[i- 1] { continue }
k := n - 1
target := -1 * nums[i]
for j := i + 1; j < n; j++ {
if j > i+ 1 && nums[j] == nums[j- 1] { continue }
for j < k && nums[j] + nums[k] > target { k-- }
if j == k { break }
if nums[j] + nums[k] == target {
ans = append(ans, []int{nums[i], nums[j], nums[k]})
}
}
}
return
}
// 删除
// 方法: 比较复杂
// 第一种情况是,如果要删除的节点没有子节点,我们只需要直接将父节点中,指向要删除节点的指针置为 null。比如图中的删除节点 55。
// 第二种情况是,如果要删除的节点只有一个子节点(只有左子节点或者右子节点),我们只需要更新父节点中,指向要删除节点的指针,让它指向要删除节点的子节点就可以了。比如图中的删除节点 13。
// 第三种情况是,如果要删除的节点有两个子节点,这就比较复杂了。我们需要找到这个节点的右子树中的最小节点,把它替换到要删除的节点上。
// 然后再删除掉这个最小节点,因为最小节点肯定没有左子节点(如果有左子结点,那就不是最小节点了),所以,我们可以应用上面两条规则来删除这个最小节点。比如图中的删除节点 18。
// 判断是否有环形链表
func hasCycle(head *ListNode) bool {
seen := make(map[*ListNode]struct{})
for head != nil {
if _, ok := seen[head]; ok {
return true
}
seen[head] = struct{}{}
head = head.Next
}
return false
}
// 合并N个升序链表 +1
/**
* Definition for singly-linked list.
* type ListNode struct {
* Val int
* Next *ListNode
* }
*/
func mergeKLists(lists []*ListNode) *ListNode {
if len(lists) == 0 {
return nil
}
result := lists[0]
for _, list := range lists {
if list == result {
continue
}
result = Merge(result, list)
}
return result
}
func Merge(l1 *ListNode, l2 *ListNode) *ListNode { //合并链表算法
if l1 == nil {
return l2
}
if l2 == nil {
return l1
}
//新建Node
resNode := &ListNode{}
if l1.Val >= l2.Val {
resNode = l2
resNode.Next = Merge(l1, l2.Next)
} else {
resNode = l1
resNode.Next = Merge(l2, l1.Next)
}
return resNode
}
// 翻转字符串
func reverseString(s []byte) {
for left, right := 0, len(s) - 1; left < right; left ++ {
s[left], s[right] = s[right], s[left]
right --
}
}
// 二叉树的右视图, [MARK]
/**
* Definition for a binary tree node.
* type TreeNode struct {
* Val int
* Left *TreeNode
* Right *TreeNode
* }
*/
// 1
// /\
// 4 2
// /\ /\
// 5 6 3
// 从根节点,向下优先 遍历右树,
// 用queue保存每一层的节点, 将每一层的最后一个节点加入res, 返回res
func rightSideView(root *TreeNode) []int {
if root == nil {
return []int{}
}
res := []int{}
queue := make([]*TreeNode, 0)
queue = append(queue, root)
for len(queue) > 0 {
//每层的节点数
length := len(queue)
//每次取queue最后一位,即为右视图看到的节点
res = append(res, queue[length - 1].Val)
for i := 0; i < length; i++ {
// 从左到右遍历一层的节点; 循环完本层节点,同时把下一层节点入Queue
node := queue[0]
queue = queue[1:]
if node.Left != nil {
queue = append(queue, node.Left)
}
if node.Right != nil {
queue = append(queue, node.Right)
}
}
}
return res
}
M2: 递归
/**
* Definition for a binary tree node.
* type TreeNode struct {
* Val int
* Left *TreeNode
* Right *TreeNode
* }
*/
func rightSideView(root *TreeNode) []int {
var result []int
if root == nil {
return result
}
digui(root, &result, 1)
return result
}
// 这里为什么还要遍历左树的节点,
// 因为 在节点没有右树的时候,需要从左树开始遍历
// 如下图
// 1
// / \
// 2 3
// /
// 4
func digui(root *TreeNode, result *[]int, i int){
// i 代表二叉树的层数, 该层还没有加入节点数,那么就加入。
if len(*result) < i {
*result = append(*result, root.Val)
}
// 优先遍历右树
if root.Right != nil {
digui(root.Right, result, i + 1)
}
// 在节点(该层)没有右树的情况下,遍历左树,那么从右视图角度,可以看到这个左树节点。
if root.Left != nil {
digui(root.Left, result, i + 1)
}
return
}
// 求两数之和为指定数字
// m1: 暴力遍历
func twoSum(nums []int, target int) []int {
for i, num := range nums {
for j := i + 1; j < len(nums); j++ {
if num + nums[j] == target {
return []int{i, j}
}
}
}
return []int{}
}
// m2: hashmap
func twoSum(nums []int, target int) []int {
hashMap := map[int]int{}
for i, num := range nums {
if p, ok := hashMap[target - num]; ok {
return []int{p, i}
}
hashMap[num] = i
}
return []int{}
}
// 反转链表
// m1: 递归
func reverseList(head *ListNode) *ListNode {
var pre *ListNode
curr := head
for curr != nil {
next := curr.Next
curr.Next = pre
pre = curr
curr = next
}
return pre
}
// m2: 迭代
func reverseList(head *ListNode) *ListNode {
if head == nil || head.Next == nil {
return head
}
newHead := reverseList(head.Next)
head.Next.Next = head
head.Next = nil
return newHead
}
// 合并两个有序链表
func mergeTwoLists(l1 *ListNode, l2 *ListNode) *ListNode {
if l1 == nil {
return l2
}
if l2 == nil {
return l1
}
// 定义一个结果节点
var res *ListNode
// 当l1节点的值大于l2节点的值,那么res指向l2的节点,从l2开始遍历,反之从l1开始
if l1.Val >= l2.Val {
res = l2
//每次新建节点,把res.Next指向它
res.Next = mergeTwoLists(l1, l2.Next)
} else {
res = l1
res.Next = mergeTwoLists(l1.Next, l2)
}
return res
}
// 旋转单向链表N位
func rotateRight(head *ListNode, k int) *ListNode {
// 旋转0位,链表为空,链表长度小于2
if k == 0 || head == nil || head.Next == nil {
return head
}
// 计算链表长度
n := 1
iter := head
for iter.Next != nil {
iter = iter.Next
n++
}
// 计算真实移动位数
add := n - k%n
if add == n {
return head
}
// 闭合链表
iter.Next = head
// 环状链表移位
for add > 0 {
iter = iter.Next
add--
}
// 当前Next即为head
ret := iter.Next
//
iter.Next = nil
return ret
}
//有序的单向链表,删除数值重复的节点
func Func(head *ListNode) *ListNode {
var pre *ListNode
curr := head
for curr != nil {
if curr.Val == curr.Next.Val {
pre.Next = curr.Next.Next
curr = curr.Next.Next
continue
}
pre = curr
curr = curr.Next
}
return pre
}
// 合并两个有序链表
func mergeTwoLists(l1 *ListNode, l2 *ListNode) *ListNode {
if l1 == nil {
return l2
}
if l2 == nil {
return l1
}
// 定义一个结果节点
var res *ListNode
// 当l1节点的值大于l2节点的值,那么res指向l2的节点,从l2开始遍历,反之从l1开始
if l1.Val >= l2.Val {
res = l2
//每次新建节点,把res.Next指向它
res.Next = mergeTwoLists(l1, l2.Next)
} else {
res = l1
res.Next = mergeTwoLists(l1.Next, l2)
}
return res
}
// 旋转单向链表N位
func rotateRight(head *ListNode, k int) *ListNode {
// 旋转0位,链表为空,链表长度小于2
if k == 0 || head == nil || head.Next == nil {
return head
}
// 计算链表长度
n := 1
iter := head
for iter.Next != nil {
iter = iter.Next
n++
}
// 计算真实移动位数
add := n - k%n
if add == n {
return head
}
// 闭合链表
iter.Next = head
// 环状链表移位
for add > 0 {
iter = iter.Next
add--
}
// 当前Next即为head
ret := iter.Next
//
iter.Next = nil
return ret
}
//有序的单向链表,删除数值重复的节点
type ListNode struct {
Val int
Next *ListNode
}
func Func(head *ListNode) *ListNode {
var pre *ListNode
curr := head
for curr != nil {
if curr.Val == curr.Next.Val {
pre.Next = curr.Next.Next
curr = curr.Next.Next
continue
}
pre = curr
curr = curr.Next
}
return pre
}
// 字符串长度不一定,最大值8
// '1wI'
1 I
| |
w w
/\ /\
1 I 1 I
输出:
['1 w 1',
'1 w I',
'I w 1',
'1 w I']
func main() {
s := "1wIwwII1"
res := TransFunc(s)
fmt.Println(res)
}
// 转义函数
// 输入: 当前字符串,
// 输出: 当前字符串,模糊匹配的字符串数组
func TransFunc(s string) []string {
var res []string
if len(s) == 1 {
if s[0] == '1' || s[0] == 'I' {
res = append(res, "1")
res = append(res, "I")
} else {
res = append(res, s)
}
return res
}
if len(s) > 1 {
head := s[0]
resNext := TransFunc(s[1:])
// 下一级字符串返回的模糊数组
for _, v := range resNext {
if head == '1' || head == 'I' {
res = append(res, "1"+v)
res = append(res, "I"+v)
} else {
res = append(res, string(head)+v)
}
}
}
return res
}
吃货算法。。
package main
import (
"fmt"
)
func main() {
list := []*St{{1, 2}, {1, 3}, {2, 3}, {4, 2}}
res := CreateFunc(3, 1, list)
fmt.Println(res)
}
type St struct {
x int
y int
}
func uniqueInts(a []int) (b []int) {
m := map[int]bool{}
for _, v := range a {
if _, ok := m[v]; !ok {
b = append(b, v)
m[v] = true
}
}
return b
}
func parseList(goal int, putList []int) bool {
for _, p := range putList {
if p == goal {
return true
}
}
return false
}
func CreateFunc(totalNum, speed int, list []*St) int {
var goalList []int
var putList []int
for _, v := range list {
time := v.x + v.y
if time%speed == 0 {
goalList = append(goalList, time)
putList = append(putList, v.x)
}
}
goalList = uniqueInts(goalList)
var goalFinalList []int
for _, v := range goalList {
if parseList(v, putList) {
continue
} else {
goalFinalList = append(goalFinalList, v)
}
}
return len(goalFinalList)
}