LeetCode 不定期刷题

//螺旋矩阵

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)
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值