叫我詹躲躲

叫我詹躲躲 查看完整档案

长沙编辑Digital Hollywood University  |  计算机 编辑前端开发  |  前端开发 编辑 zhanhongzhu.top 编辑
编辑

热爱前端,热爱技术。积极乐观。喜欢的朋友,可以关注我的公众号@叫我詹躲躲。
个人网站:https://zhanhongzhu.top
掘金:https://juejin.im/user/5cc675...
CSDN:https://blog.csdn.net/weixin_...
简书:https://www.jianshu.com/u/b8d...
语雀:https://www.yuque.com/xiatian...

个人动态

叫我詹躲躲 发布了文章 · 4月14日

[剑指 Offer 55 - I. 二叉树的深度] | 刷题打卡[5]

c9b440df07605539b510a39e5ceb6007.png

一、题目描述:

输入一棵二叉树的根节点,求该树的深度。从根节点到叶节点依次经过的节点(含根、叶节点)形成树的一条路径,最长路径的长度为树的深度。

例如
给定二叉树 [3,9,20,null,null,15,7],

    3
   / \
  9  20
    /  \
   15   7

返回它的最大深度 3 。

提示:
节点总数 <= 10000

二、思路分析:

二叉树的深度

二叉树的深度:树中的一个节点的深度是它到根节点的路径上的边的条数。(Robert Sedgewick和Kevin Wayne所著的《算法》第4版)

树中某节点的高度是指从该节点到叶子节点的最长简单路径边的条数。 树的高度等于所有节点的最大深度(即树的深度)。

树的深度

1. 一棵树只有一个节点或没有节点,它的深度是0;<br/>
2. 二叉树的根节点只有左子树而没有右子树,那么可以判断,二叉树的深度应该是其左子树的深度加1;<br/>
3. 二叉树的根节点只有右子树而没有左子树,那么可以判断,那么二叉树的深度应该是其右树的深度加1;<br/>
4. 二叉树的根节点既有右子树又有左子树,那么可以判断,那么二叉树的深度应该是其左右子树的深度较大值加1。<br/>

三、AC 代码:

var maxDepth = function(root) {
    //一个节点都没有
    if(root===null){
        return 0
    }
    //只有一个根节点
    if(root.left===null && root.right===null){
        return 1
    }
    //递归左子树
    let leftMax = maxDepth(root.left)
    //递归右子树
    let rightMax = maxDepth(root.right)
    //返回左右子树的深度较大值加1
    return Math.max(leftMax,rightMax)+1
};

四、总结:

1.本题考察对二叉树深度的基本理解。什么是树的深度,以及树深度的计算规则和技巧。

查看原文

赞 0 收藏 0 评论 0

叫我詹躲躲 发布了文章 · 4月13日

[LeetCode 179. 最大数] | 刷题打卡[4]

c9b440df07605539b510a39e5ceb6007.png

一、题目描述:

给定一组非负整数 nums,重新排列每个数的顺序(每个数不可拆分)使之组成一个最大的整数。

注意:输出结果可能非常大,所以你需要返回一个字符串而不是整数。

示例 1:

输入:nums = [10,2]
输出:"210"

示例 2:

输入:nums = [3,30,34,5,9]
输出:"9534330"

示例 3:

输入:nums = [1]
输出:"1"

示例 4:

输入:nums = [10]
输出:"10"

提示:

    1 <= nums.length <= 100
    0 <= nums[i] <= 109

二、思路分析:

1.使相邻元素按字符的ASCII码顺序排序;如 a = 3,b = 30;<br/>
2.直接排需要,会按照数字进行排序,由此转换成字符串进行排序;<br/>

三、AC 代码:

JavaScript 解题一

/**
 * @param {number[]} nums
 * @return {string}
 */
var largestNumber = function (nums) {
    let ret = nums.sort((a, b) => {
        return ("" + b + a) - ("" + a + b)
    })
    if (nums[0] === 0) {
        return '0';
    }
    return nums.join("")
};

JavaScript 解题二

该解法参考官方解法:

图片.png

图片.png

/**
 * @param {number[]} nums
 * @return {string}
 */
var largestNumber = function (nums) {
    nums.sort((a, b) => {
        let x = 10, y = 10
        while (x <= a) {
            x *= 10
        }
        while(y<=b){
            y*=10
        }
        return ("" + a*y+x) - ("" + y*a+b)
    })
    if (nums[0] === 0) {
        return '0';
    }
    return nums.join("")
};

四、总结:

1.本题利用了sort排序规则,对字符串根据ASCII表进行排序,数字值越大,排在后面;<br/>
2.拼接字符串得到最大值;<br/>

参考解法

官方解法

查看原文

赞 0 收藏 0 评论 0

叫我詹躲躲 发布了文章 · 4月13日

[LeetCode 逐步求和得到正数的最小值] | 刷题打卡[3]

c9b440df07605539b510a39e5ceb6007.png

一、题目描述:

给你一个整数数组 nums 。你可以选定任意的 正数 startValue 作为初始值。
你需要从左到右遍历 nums 数组,并将 startValue 依次累加上 nums 数组中的值。
请你在确保累加和始终大于等于 1 的前提下,选出一个最小的 正数 作为 startValue 。

示例 1:

输入:nums = [-3,2,-3,4,2]
输出:5
解释:如果你选择 startValue = 4,在第三次累加时,和小于 1 。
                累加求和
                startValue = 4 | startValue = 5 | nums
                  (4 -3 ) = 1  | (5 -3 ) = 2    |  -3
                  (1 +2 ) = 3  | (2 +2 ) = 4    |   2
                  (3 -3 ) = 0  | (4 -3 ) = 1    |  -3
                  (0 +4 ) = 4  | (1 +4 ) = 5    |   4
                  (4 +2 ) = 6  | (5 +2 ) = 7    |   2

示例 2:

输入:nums = [1,2]
输出:1
解释:最小的 startValue 需要是正数。

示例 3:

输入:nums = [1,-2,-3]
输出:5

提示:

1 <= nums.length <= 100
-100 <= nums[i] <= 100

二、思路分析:

1.保证每一步都大于0
2.从左到右相加求和
3.和小于1时更新最小值,取相反数+1,更新和
4.全部为正数,返回1,否则返回最小值

三、AC 代码:

/**
 * @param {number[]} nums
 * @return {number}
 */
var minStartValue = function (nums) {
    //保证每一步都大于0
    let sum = 0, min = 0
    for (let i = 0; i < nums.length; i++) {
        //从左到右相加
        sum += nums[i]
        //和小于1时更新最小值,取相反数+1,更新和
        if (sum < 1) {
            let temp = 1 - sum
            sum += temp
            min += temp
        }
    }
    //全部为正数,返回1
    return min || 1
};

四、总结:

1.和小于1时更新最小值,取相反数+1,更新和。继续加油!

查看原文

赞 0 收藏 0 评论 0

叫我詹躲躲 发布了文章 · 4月11日

[LeetCode264. 丑数 II] 三指针 | 刷题打卡[2]

90d1c7657a694816e344912feddf040f.jpg

一、题目描述:

给你一个整数 n ,请你找出并返回第 n 个 丑数 。
丑数 就是只包含质因数 2、3 和/或 5 的正整数

二、思路分析:

三指针

1.2,3,5分别对应指针i2,i3,i5,遍历找到当前指针

2.移动i对于的当前指针,并记录结果

3.找到数组最后一位即是第n个丑数

三、AC 代码:

javascript

/**
 * @param {number} n
 * @return {number}
 */
var nthUglyNumber = function (n) {
    let i2 = 0,//2对应的指针
        i3 = 0,//3对应的指针
        i5 = 0,//5对应的指针
        dp = [1] //dp数组
    for (let i = 1; i < n; i++) {
        //计算i对应当前那个指针
        let min = Math.min(dp[i2] * 2, dp[i3] * 3, dp[i5] * 5)
        //指针分别向前移动
        if (min === dp[i2] * 2) i2++ 
        if (min === dp[i3] * 3) i3++
        if (min === dp[i5] * 5) i5++
        dp[i] = min
    }
    return dp[dp.length - 1]
};

Python

class Solution(object):
    def nthUglyNumber(self, n):
        """
        :type n: int
        :rtype: int
        """
        i2,i3,i5,dp = 0,0,0,[1]
        for _ in range(1,n):
        # 计算i对应当前那个指针
            minMars = min(dp[i2] * 2, dp[i3] * 3, dp[i5] * 5)
            # 指针分别向前移动
            if minMars == dp[i2] * 2:
               i2 = i2+1
            if minMars == dp[i3] * 3:
               i3 = i3+1
            if minMars == dp[i5] * 5:
               i5 = i5+1
            dp.append(minMars)
        return dp[len(dp) - 1]

Typescript

function nthUglyNumber(n: number): number {
    let i2:number = 0,//2对应的指针
        i3:number = 0,//3对应的指针
        i5:number = 0,//5对应的指针
        dp:number[] = [1] //dp数组
    for (let i = 1; i < n; i++) {
        //计算i对应当前那个指针
        let min = Math.min(dp[i2] * 2, dp[i3] * 3, dp[i5] * 5)
        //指针分别向前移动
        if (min === dp[i2] * 2) i2++ 
        if (min === dp[i3] * 3) i3++
        if (min === dp[i5] * 5) i5++
        dp[i] = min
    }
    return dp[dp.length - 1]
};

Go

func nthUglyNumber(n int) int {
    dp := make([]int, n+1)
    dp[1] = 1
    i2, i3, i5 := 1, 1, 1
    for i := 2; i <= n; i++ {
        //计算i对应当前那个指针
        x2, x3, x5 := dp[i2]*2, dp[i3]*3, dp[i5]*5
        dp[i] = min(min(x2, x3), x5)
        if dp[i] == x2 {
            i2++
        }
        if dp[i] == x3 {
            i3++
        }
        if dp[i] == x5 {
            i5++
        }
    }
    return dp[n]
}

//由于go语言里面没有min()函数,自己构建一个
func min(a, b int) int {
    if a > b {
        return b
    }
    return a
}

四、总结:

1.三指针计算当前i对应的丑数,记录丑数到数组,取最后面一位。继续加油!

查看原文

赞 0 收藏 0 评论 0

叫我詹躲躲 发布了文章 · 4月10日

[LeetCode连续子数组的最大和] | 刷题打卡[1]

90d1c7657a694816e344912feddf040f.jpg

一、题目描述:

输入一个整型数组,数组中的一个或连续多个整数组成一个子数组。求所有子数组的和的最大值。
要求时间复杂度为O(n)。

二、思路分析:

动态规划

1.从数组第一个元素开始,分别累加数组的元素<br/>
2.当求和到当前元素为负数和时,重新计算下一轮数组和,并记录当前的最大和<br/>
3.比较每轮数组和,返回最大值;<br/>

三、AC 代码:

javascript

/**
 * @param {number[]} nums
 * @return {number}
 */
var maxSubArray = function (nums) {
    //数组长度为1时,返回数组第一个元素
    if(nums.length===1) return nums[0]
    let dp = nums[0], max = nums[0]
    for (let i = 1; i < nums.length; i++) {
        //当和小于0时,丢弃这个结果,当前元素重新开始求和
        dp = dp > 0 ? dp + nums[i] : nums[i]
        //将之前计算的和,求出最大值
        max = Math.max(dp, max)
    }
    return max
};

Python

class Solution(object):
    def maxSubArray(self, nums):
        """
        :type nums: List[int]
        :rtype: int
        """
        if(len(nums)==1):
            return nums[0]
        dp,ret = nums[0],nums[0]
        for i in range(1,len(nums)):
            if dp>0:
                dp = dp+nums[i]
            else:
                dp = nums[i]
            ret = max(dp,ret)
        return ret

Typescript

function maxSubArray(nums: number[]): number {
    //数组长度为1时,返回数组第一个元素
    if (nums.length === 1) return nums[0]
    let temp:number= nums[0], max:number = nums[0]
    for (let i = 1; i < nums.length; i++) {
        //当和小于0时,丢弃这个结果,当前元素重新开始求和
        temp = temp > 0 ? temp + nums[i] : nums[i]
        //将之前计算的和,求出最大值
        max = Math.max(temp, max)
    }
    return max
};

Go

func maxSubArray(nums []int) int {
    res:=nums[0]
    for i:=1;i<len(nums) ;i++  {
        //求和,小于0时,和等于0,重新求和
        nums[i]+=max(nums[i-1],0)
        //更新最大记录值
        res=max(res,nums[i])
    }
    return res
}
//由于go语言里面没有max()函数,自己构建一个
func max(a,b int) int{
    if a>b{
        return a
    }
    return b
}

四、总结:

1.动态求和,动态更新最大记录。继续加油!

查看原文

赞 0 收藏 0 评论 0

叫我詹躲躲 发布了文章 · 4月5日

Golang语言[6] 递增的三元子序列/笨阶乘/矩阵查找/直方图的水量 |Go主题月

90d1c7657a694816e344912feddf040f.jpg

递增的三元子序列

给你一个整数数组 nums ,判断这个数组中是否存在长度为 3 的递增子序列。
如果存在这样的三元组下标 (i, j, k) 且满足 i < j < k ,使得 nums[i] < nums[j] < nums[k] ,返回 true ;否则,返回 false 。

示例 1:

输入:nums = [1,2,3,4,5]
输出:true
解释:任何 i < j < k 的三元组都满足题意

示例 2:

输入:nums = [5,4,3,2,1]
输出:false
解释:不存在满足题意的三元组

示例 3:

输入:nums = [2,1,5,0,4,6]
输出:true
解释:三元组 (3, 4, 5) 满足题意,因为 nums[3] == 0 < nums[4] == 4 < nums[5] == 6

提示:

    1 <= nums.length <= 105
    -231 <= nums[i] <= 231 - 1

进阶:你能实现时间复杂度为 O(n) ,空间复杂度为 O(1) 的解决方案吗?

解题思路一

1.找到最小值和次小的值,通过跟当前元素进行比较;<br/>
2.更新最小值和次小值<br/>
2.否则即满足条件<br/>

//引入math库
import (
    "math"
)

func increasingTriplet(nums []int) bool {
    //记录最小值和第二小的值
    m1, m2 := math.MaxInt32, math.MaxInt32
    for _, v := range nums {
        //找到子序列第一个元素,不断更新
        if m1 >= v {
            m1 = v
        } else if m2 >= v {
            //找到子序列第二个元素,不断更新
            m2 = v
        } else {
            //找到第三个,满足要求
            return true
        }
    }
    return false
}

Javascript

/**
 * @param {number[]} nums
 * @return {boolean}
 */
var increasingTriplet = function (nums) {
    let min = nums[0], temp = Number.MAX_VALUE
    // 最小值,中间值
    for (let i = 1; i < nums.length-1; i++) {
        //找到最小值
        min = Math.min(min, nums[i])
        //找到中间值
        if (nums[i] > min) {
            temp = nums[i]
        }
        //找到第三个值
        if (temp < nums[i + 1]) {
            return true
        }
    }
    return false
};

编写一个高效的算法来判断 m x n 矩阵中,是否存在一个目标值。该矩阵具有如下特性:

每行中的整数从左到右按升序排列。
每行的第一个整数大于前一行的最后一个整数。
示例 1:

输入:matrix = [[1,3,5,7],[10,11,16,20],[23,30,34,60]], target = 3
输出:true

示例 2:

输入:matrix = [[1,3,5,7],[10,11,16,20],[23,30,34,60]], target = 13
输出:false

提示:

    m == matrix.length
    n == matrix[i].length
    1 <= m, n <= 100
    -104 <= matrix[i][j], target <= 104

Go 数组查找

func searchMatrix(matrix [][]int, target int) bool {
    m := len(matrix)
    n := len(matrix[0])
    var i = 0
    for i < m && n > 0 {
        if target == matrix[i][n-1] {
            return true
        } else if target < matrix[i][n-1] {
            n--
        } else {
            i++
        }
    }
    return false
}

javascript 暴力解法

/**
 * @param {number[][]} matrix
 * @param {number} target
 * @return {boolean}
 */
 var searchMatrix = function(matrix, target) {
    for(let i=0;i<matrix.length;i++){
        for(let j=0;j<matrix[0].length;j++){
            if(matrix[i][j]===target){
                return true
            }
        }
    }
    return false
};

javascript 数组查找

/**
 * @param {number[][]} matrix
 * @param {number} target
 * @return {boolean}
 */
/*
    以二维数组左下角为原点,建立直角坐标轴。
    若当前数字大于了查找数,查找往上移一位。
    若当前数字小于了查找数,查找往右移一位。
*/
 var searchMatrix = function(matrix, target) {
    let x = matrix.length-1,y = 0
    while(x>=0 && y<matrix[0].length){
        if(matrix[x][y]===target){
            return true
        }else if(matrix[x][y]>target){
            x--
        }else{
            y++
        }
    }
    return false
};

javascript 二分法

/**
 * @param {number[][]} matrix
 * @param {number} target
 * @return {boolean}
 */
 var searchMatrix = function(matrix, target) {
    let m = matrix.length,n=matrix[0].length
    let low = 0,high = m*n-1
    while(low<=high){
        let mid = Math.floor((high-low)/2)+low //中位
        let x = matrix[Math.floor(mid/n)][mid%n] //所在的值
        if(x<target){
            low = mid+1
        }else if(x>target){
            high = mid-1
        }else{
            return true
        }
    }
    return false
};

Typescript 以上两种也可以改为ts

function searchMatrix(matrix: number[][], target: number): boolean {
    let x: number = matrix.length - 1, y:number = 0
    while (x >= 0 && y < matrix[0].length) {
        if (matrix[x][y] === target) {
            return true
        } else if (matrix[x][y] > target) {
            x--
        } else {
            y++
        }
    }
    return false
};

python 暴力解法

class Solution(object):
     def searchMatrix(self, matrix, target):
        for i in range(len(matrix)):
            for j in range(len(matrix[0])):
                if matrix[i][j]==target:
                    return True
        return False

python any函数

any() 函数用于判断给定的可迭代参数 iterable 是否全部为 False,则返回 False,如果有一个为 True,则返回 True。元素除了是 0、空、FALSE 外都算 TRUE。

语法

def any(iterable):
    for element in iterable:
        if element:
            return True
    return False

解法

class Solution(object):
     def searchMatrix(self, matrix, target):
        return any(target in row for row in matrix)

笨阶乘

通常,正整数 n 的阶乘是所有小于或等于 n 的正整数的乘积。例如,factorial(10) = 10 9 8 7 6 5 4 3 2 * 1。
相反,我们设计了一个笨阶乘 clumsy:在整数的递减序列中,我们以一个固定顺序的操作符序列来依次替换原有的乘法操作符:乘法(*),除法(/),加法(+)和减法(-)。

例如,clumsy(10) = 10 9 / 8 + 7 - 6 5 / 4 + 3 - 2 * 1。然而,这些运算仍然使用通常的算术运算顺序:我们在任何加、减步骤之前执行所有的乘法和除法步骤,并且按从左到右处理乘法和除法步骤。

另外,我们使用的除法是地板除法(floor division),所以 10 * 9 / 8 等于 11。这保证结果是一个整数。

实现上面定义的笨函数:给定一个整数 N,它返回 N 的笨阶乘。

示例 1:

输入:4
输出:7
解释:7 = 4 * 3 / 2 + 1

示例 2:

输入:10
输出:12
解释:12 = 10 * 9 / 8 + 7 - 6 * 5 / 4 + 3 - 2 * 1

提示:

    1 <= N <= 10000
    -2^31 <= answer <= 2^31 - 1  (答案保证符合 32 位整数。

GOLang

func clumsy(N int) int {
    if N == 1 {
        return 1
    } else if N == 2 {
        return 2
    } else if N == 3 {
        return 6
    } else if N == 4 {
        return 7
    }

    if N%4 == 0 {
        return N + 1
    } else if N%4 <= 2 {
        return N + 2
    } else {
        return N - 1
    }
}

javascript

/**
 * @param {number} N
 * @return {number}
 */
var clumsy = function (N) {
    if (N === 1) {
        return 1
    } else if (N === 2) {
        return 2
    } else if (N === 3) {
        return 6
    } else if (N === 4) {
        return 7
    }

    if (N % 4 === 0) {
        return N + 1
    } else if (N % 4 <= 2) {
        return N + 2
    } else {
        return N - 1
    }
};

python

class Solution(object):
    def clumsy(self, N):
        """
        :type N: int
        :rtype: int
        """
        if N == 1:
            return 1
        elif N == 2:
            return 2
        elif N == 3:
            return 6
        elif N == 4:
            return 7

        if N % 4 == 0:
            return N + 1
        elif N % 4 <= 2:
            return N + 2
        else:
             return N - 1

typescript

function clumsy(N: number): number {
    if (N === 1) {
        return 1
    } else if (N === 2) {
        return 2
    } else if (N === 3) {
        return 6
    } else if (N === 4) {
        return 7
    }

    if (N % 4 === 0) {
        return N + 1
    } else if (N % 4 <= 2) {
        return N + 2
    } else {
        return N - 1
    }
};

17.21. 直方图的水量

难度:[困难]

给定一个直方图(也称柱状图),假设有人从上面源源不断地倒水,最后直方图能存多少水量?直方图的宽度为 1。

图片.png

上面是由数组 [0,1,0,2,1,0,1,3,2,1,2,1] 表示的直方图,在这种情况下,可以接 6 个单位的水(蓝色部分表示水)。 感谢 Marcos 贡献此图。

示例:

输入: [0,1,0,2,1,0,1,3,2,1,2,1]
输出: 6

【思路】动态规划

1.记录height中的每个元素,从左向右扫描并记录右边的最大高度;<br/>
2.记录height中的每个元素,从右向左扫描并记录右边的最大高度;<br/>
3.将左右位置元素对比取最小的元素,减去数组当前元素的高度。<br/>

从左向右扫描并记录右边的最大高度

从右向左扫描并记录右边的最大高度

取高度最小值

go

func trap(height []int) int {
    n := len(height)
    if n == 0 {
        return 0
    }
    //记录左边每个元素最大高度
    leftMax := make([]int, n)
    leftMax[0] = height[0]
    for i := 1; i < n; i++ {
        leftMax[i] = max(leftMax[i-1], height[i])
    }
    //记录左边每个元素最大高度
    rightMax := make([]int, n)
    rightMax[n-1] = height[n-1]
    for i := n - 2; i >= 0; i-- {
        rightMax[i] = max(rightMax[i+1], height[i])
    }
    fmt.Println(leftMax, rightMax)
    ret := 0
    for j := 0; j < n; j++ {
        ret += (min(leftMax[j], rightMax[j]) - height[j])
    }
    return ret
}

//由于Go语言里面没有max(),min()需要自己实现一个
func max(a, b int) int {
    if a-b > 0 {
        return a
    }
    return b
}
func min(a, b int) int {
    if a-b > 0 {
        return b
    }
    return a
}

Javascript

var trap = function (height) {
    let len = height.length
    if (len === 0) return 0
    //记录左边每个矩形最大高度
    let left = Array(len).fill(0)
    left[0] = height[0]
    for (let i = 1; i < len; ++i) {
        left[i] = Math.max(left[i - 1], height[i])
    }
    //记录右边每个矩形最大高度
    let right = Array(len).fill(0)
    right[len - 1] = height[len - 1]
    for (let i = len - 2; i >= 0; --i) {
        right[i] = Math.max(right[i + 1], height[i])
    }
    //记录结果
    let ret = 0
    for (let i = 0; i < len; ++i) {
        //左右对比取最小边界,减去当前矩形高度
        ret += Math.min(left[i], right[i]) - height[i]
    }
    return ret
};

Typescript

function trap(height) {
    var len = height.length;
    if (len === 0)
        return 0;
    //记录左边每个矩形最大高度
    var left = Array(len);
    left[0] = height[0];
    for (var i = 1; i < len; ++i) {
        left[i] = Math.max(left[i - 1], height[i]);
    }
    //记录右边每个矩形最大高度
    var right = Array(len);
    right[len - 1] = height[len - 1];
    for (var i = len - 2; i >= 0; --i) {
        right[i] = Math.max(right[i + 1], height[i]);
    }
    //记录结果
    var ret = 0;
    for (var i = 0; i < len; ++i) {
        //左右对比取最小边界,减去当前矩形高度
        ret += Math.min(left[i], right[i]) - height[i];
    }
    return ret;
}

python

class Solution(object):
    def trap(self, height):
        """
        :type height: List[int]
        :rtype: int
        """
        if not height:
            return 0
        # 数组长度
        n = len(height)

        # 记录左边每个矩形最大高度
        left = [0]*n
        left[0] = height[0]
        for i in range(1,n):
            left[i] = max(left[i - 1], height[i])

        # 记录右边每个矩形最大高度
        right = [0]*n
        right[n - 1] = height[n - 1]
        for i in range(n-2,-1,-1):
            right[i] = max(right[i + 1], height[i])
        # 记录结果
        ret = sum(min(left[i], right[i]) - height[i] for i in range(n)) 
        return ret

继续加油!

查看原文

赞 0 收藏 0 评论 0

叫我詹躲躲 发布了文章 · 4月2日

【算法】[困难]-直方图的水量-动态规划

17.21. 直方图的水量

难度:[困难]

给定一个直方图(也称柱状图),假设有人从上面源源不断地倒水,最后直方图能存多少水量?直方图的宽度为 1。

图片.png

上面是由数组 [0,1,0,2,1,0,1,3,2,1,2,1] 表示的直方图,在这种情况下,可以接 6 个单位的水(蓝色部分表示水)。 感谢 Marcos 贡献此图。

示例:

输入: [0,1,0,2,1,0,1,3,2,1,2,1]
输出: 6

【思路】动态规划

1.记录height中的每个元素,从左向右扫描并记录右边的最大高度;<br/>
2.记录height中的每个元素,从右向左扫描并记录右边的最大高度;<br/>
3.将左右位置元素对比取最小的元素,减去数组当前元素的高度。<br/>

从左向右扫描并记录右边的最大高度

从右向左扫描并记录右边的最大高度

取高度最小值

Javascript

var trap = function (height) {
    let len = height.length
    if (len === 0) return 0
    //记录左边每个矩形最大高度
    let left = Array(len).fill(0)
    left[0] = height[0]
    for (let i = 1; i < len; ++i) {
        left[i] = Math.max(left[i - 1], height[i])
    }
    //记录右边每个矩形最大高度
    let right = Array(len).fill(0)
    right[len - 1] = height[len - 1]
    for (let i = len - 2; i >= 0; --i) {
        right[i] = Math.max(right[i + 1], height[i])
    }
    //记录结果
    let ret = 0
    for (let i = 0; i < len; ++i) {
        //左右对比取最小边界,减去当前矩形高度
        ret += Math.min(left[i], right[i]) - height[i]
    }
    return ret
};

go

func trap(height []int) int {
    n := len(height)
    if n == 0 {
        return 0
    }
    //记录左边每个元素最大高度
    leftMax := make([]int, n)
    leftMax[0] = height[0]
    for i := 1; i < n; i++ {
        leftMax[i] = max(leftMax[i-1], height[i])
    }
    //记录左边每个元素最大高度
    rightMax := make([]int, n)
    rightMax[n-1] = height[n-1]
    for i := n - 2; i >= 0; i-- {
        rightMax[i] = max(rightMax[i+1], height[i])
    }
    fmt.Println(leftMax, rightMax)
    ret := 0
    for j := 0; j < n; j++ {
        ret += (min(leftMax[j], rightMax[j]) - height[j])
    }
    return ret
}

//由于Go语言里面没有max(),min()需要自己实现一个
func max(a, b int) int {
    if a-b > 0 {
        return a
    }
    return b
}
func min(a, b int) int {
    if a-b > 0 {
        return b
    }
    return a
}

Typescript

function trap(height) {
    var len = height.length;
    if (len === 0)
        return 0;
    //记录左边每个矩形最大高度
    var left = Array(len);
    left[0] = height[0];
    for (var i = 1; i < len; ++i) {
        left[i] = Math.max(left[i - 1], height[i]);
    }
    //记录右边每个矩形最大高度
    var right = Array(len);
    right[len - 1] = height[len - 1];
    for (var i = len - 2; i >= 0; --i) {
        right[i] = Math.max(right[i + 1], height[i]);
    }
    //记录结果
    var ret = 0;
    for (var i = 0; i < len; ++i) {
        //左右对比取最小边界,减去当前矩形高度
        ret += Math.min(left[i], right[i]) - height[i];
    }
    return ret;
}

python

class Solution(object):
    def trap(self, height):
        """
        :type height: List[int]
        :rtype: int
        """
        if not height:
            return 0
        # 数组长度
        n = len(height)

        # 记录左边每个矩形最大高度
        left = [0]*n
        left[0] = height[0]
        for i in range(1,n):
            left[i] = max(left[i - 1], height[i])

        # 记录右边每个矩形最大高度
        right = [0]*n
        right[n - 1] = height[n - 1]
        for i in range(n-2,-1,-1):
            right[i] = max(right[i + 1], height[i])
        # 记录结果
        ret = sum(min(left[i], right[i]) - height[i] for i in range(n)) 
        return ret

继续加油!哦里给

查看原文

赞 0 收藏 0 评论 0

叫我詹躲躲 发布了文章 · 3月30日

【算法】搜索二维矩阵 暴力解法&二分法 4种语言

9b919b58d1f347d600821762d79817c7.jpg

编写一个高效的算法来判断 m x n 矩阵中,是否存在一个目标值。该矩阵具有如下特性:

每行中的整数从左到右按升序排列。
每行的第一个整数大于前一行的最后一个整数。

示例 1:

输入:matrix = [[1,3,5,7],[10,11,16,20],[23,30,34,60]], target = 3
输出:true

示例 2:

输入:matrix = [[1,3,5,7],[10,11,16,20],[23,30,34,60]], target = 13
输出:false

提示:

    m == matrix.length
    n == matrix[i].length
    1 <= m, n <= 100
    -104 <= matrix[i][j], target <= 104

javascript 暴力解法

/**
 * @param {number[][]} matrix
 * @param {number} target
 * @return {boolean}
 */
 var searchMatrix = function(matrix, target) {
    for(let i=0;i<matrix.length;i++){
        for(let j=0;j<matrix[0].length;j++){
            if(matrix[i][j]===target){
                return true
            }
        }
    }
    return false
};

javascript 数组查找

/**
 * @param {number[][]} matrix
 * @param {number} target
 * @return {boolean}
 */
/*
    以二维数组左下角为原点,建立直角坐标轴。
    若当前数字大于了查找数,查找往上移一位。
    若当前数字小于了查找数,查找往右移一位。
*/
 var searchMatrix = function(matrix, target) {
    let x = matrix.length-1,y = 0
    while(x>=0 && y<matrix[0].length){
        if(matrix[x][y]===target){
            return true
        }else if(matrix[x][y]>target){
            x--
        }else{
            y++
        }
    }
    return false
};

javascript 二分法

/**
 * @param {number[][]} matrix
 * @param {number} target
 * @return {boolean}
 */
 var searchMatrix = function(matrix, target) {
    let m = matrix.length,n=matrix[0].length
    let low = 0,high = m*n-1
    while(low<=high){
        let mid = Math.floor((high-low)/2)+low //中位
        let x = matrix[Math.floor(mid/n)][mid%n] //所在的值
        if(x<target){
            low = mid+1
        }else if(x>target){
            high = mid-1
        }else{
            return true
        }
    }
    return false
};

Typescript 以上两种也可以改为ts

function searchMatrix(matrix: number[][], target: number): boolean {
    let x: number = matrix.length - 1, y:number = 0
    while (x >= 0 && y < matrix[0].length) {
        if (matrix[x][y] === target) {
            return true
        } else if (matrix[x][y] > target) {
            x--
        } else {
            y++
        }
    }
    return false
};

python 暴力解法

class Solution(object):
     def searchMatrix(self, matrix, target):
        for i in range(len(matrix)):
            for j in range(len(matrix[0])):
                if matrix[i][j]==target:
                    return True
        return False

python any函数

any() 函数用于判断给定的可迭代参数 iterable 是否全部为 False,则返回 False,如果有一个为 True,则返回 True。元素除了是 0、空、FALSE 外都算 TRUE。

语法

def any(iterable):
    for element in iterable:
        if element:
            return True
    return False

解法

class Solution(object):
     def searchMatrix(self, matrix, target):
        return any(target in row for row in matrix)

Go 数组查找

func searchMatrix(matrix [][]int, target int) bool {
    m := len(matrix)
    n := len(matrix[0])
    var i = 0
    for i < m && n > 0 {
        if target == matrix[i][n-1] {
            return true
        } else if target < matrix[i][n-1] {
            n--
        } else {
            i++
        }
    }
    return false
}
第一次尝试用4种语言去解一道题目,继续加油!
查看原文

赞 0 收藏 0 评论 0

叫我詹躲躲 发布了文章 · 3月30日

Golang语言 Gin框架环境配置、报错处理、接口调用、配置和日志管理|Go主题月

213122132132123131.gif
安装:
下载并安装

go get -u github.com/gin-gonic/gin

安装失败的话,直接打开 github.com/gin-gonic/gin,下载压缩包,并在GOPATH路径的src目录下面建立github.com,解压到这个目录下面;

遇到的报错信息:

Go 项目编译:cannot find package "." in:*

将缺少依赖的包重新安装一次即可解决问题。

go: inconsistent vendoring in xxx报错


修改GOPAHT,改到非GOROOT路径。GOROOT是GO语言安装路径,GOPATH是GO语言编译环境所需路径,因此二者不能为同一路径

新建项目

GOPATH目录下面的src下面新建一个文件夹app,使用命令

go mod init

新建 main.go,写出我们的第一个程序

package main
import "github.com/gin-gonic/gin"

func main() {
    r := gin.Default()
    r.GET("/", func(c *gin.Context) {
        c.JSON(200, gin.H{
            "name": "叫我詹躲躲",
            "gend": "男",
        })
    })
    r.Run(":8080")
}

运行程序

go run main.go


浏览器运行:

生成JSON

func AsciiJSON() {
    r := gin.Default()
    r.GET("/", func(c *gin.Context) {
        c.JSON(200, gin.H{
            "name": "叫我詹躲躲",
            "gend": "男",
        })
    })
    r.Run(":8080")
}

调用

package main
import (
    "app/function"
    "github.com/gin-gonic/gin"
)

func main() {
    //使用AsciiJSON生成带有转义的非ASCII字符的纯ASCII JSON。
    function.AsciiJSON()
}

测试get请求

绑定表单数据请求与自定义结构

//绑定表单数据请求与自定义结构
type StructA struct {
    FieldA string `form:"field_a"`
}
type StructB struct {
    NestedStruct StructA
    FieldB       string `form:"field_b"`
}

//get请求
func GetFormData(c *gin.Context) {
    var b StructB
    c.Bind(&b)
    c.JSON(200, gin.H{
        "a": b.NestedStruct,
        "b": b.FieldB,
    })
}

调用

package main
import (
    "app/function"
    "github.com/gin-gonic/gin"
)

func main() {
    //将表单数据请求与自定义结构绑定
    r := gin.Default()
    //测试get请求
    r.GET("/getFormData", function.GetFormData)
    r.Run()
}

查询返回信息

//绑定查询字符串或发布数据
type PersonInfo struct {
    Name    string `form:"name"`
    Address string `form:"address"`
    Memo    string `form:"memo"`
}

//返回信息
func QueryInfo(c *gin.Context) {
    var person PersonInfo
    if c.ShouldBind(&person) == nil {
        log.Println(person.Name)
        log.Println(person.Address)
        log.Println(person.Memo)
    }
    c.String(200, "Success")
}

调用

package main
import (
    "app/function"
    "github.com/gin-gonic/gin"
)

func main() {
    r := gin.Default()
    //查询返回信息
    r.GET("/queryInfo", function.QueryInfo)
    r.Run()
}

自定义HTTP配置

http.ListenAndServe(":8080", router)

或者

s := &http.Server{
    Addr:           ":8080",
    Handler:        router,
    ReadTimeout:    10 * time.Second,
    WriteTimeout:   10 * time.Second,
    MaxHeaderBytes: 1 << 20,
}
s.ListenAndServe()

自定义日志文件

router := gin.New()
router.Use(gin.LoggerWithFormatter(func(param gin.LogFormatterParams) string {
    return fmt.Sprintf("%s - [%s] \"%s %s %s %d %s \"%s\" %s\"\n",
            param.ClientIP,
            param.TimeStamp.Format(time.RFC1123),
            param.Method,
            param.Path,
            param.Request.Proto,
            param.StatusCode,
            param.Latency,
            param.Request.UserAgent(),
            param.ErrorMessage,
    )
}))
router.Use(gin.Recovery())
router.GET("/ping", func(c *gin.Context) {
    c.String(200, "pong")
})
router.Run(":8080

参考文档

1.解决GO语言安装air框架时遇到go: inconsistent vendoring问题
2.Glide cannot find package “.” in
3.warning: GOPATH set to GOROOT (/usr/local/go) has no effect
4.gin官方文档
5.Gin框架中文文档
6.Go 不同文件之间的引用

查看原文

赞 0 收藏 0 评论 0

叫我詹躲躲 发布了文章 · 3月29日

Golang语言(打卡✏️第四天)fmt格式化工具|Go主题月

image

Println输出

Print系列函数会将内容输出到系统的标准输出,区别在于Print函数直接输出内容,Printf函数支持格式化输出字符串,Println函数会在输出内容的结尾添加一个换行符。

fmt.Println("Println输出,尾部会有换行符")
print("print输出")

Fprint

Fprint系列函数会将内容输出到一个io.Writer接口类型的变量w中,我们通常用这个函数往文件中写入内容。

实例:

// 向标准输出写入内容
fmt.Fprintln(os.Stdout, "向标准输出写入内容")
fileObj, err := os.OpenFile("./test.txt", os.O_CREATE|os.O_WRONLY|os.O_APPEND, 0644)
if err != nil {
fmt.Println("打开文件出错,err:", err)
return
}
name := "叫我詹躲躲"
// 向打开的文件句柄中写入内容
fmt.Fprintf(fileObj, "往文件中写如信息:%s", name)

//只要满足io.Writer接口的类型都支持写入。

Sprint
Sprint系列函数会把传入的数据生成并返回一个字符串。

实例:

a:=fmt.Sprint("叫我詹躲躲")
fmt.Println(a) //叫我詹躲躲

fmt.Sprint("我是%s",a) //叫我詹躲躲

Errorf

Errorf函数根据format参数生成格式化字符串并返回一个包含该字符串的错误。
通常使用这种方式来自定义错误类型。

fmt.Errorf("这是一个报错信息!")
fmt.Errorf函数新加了一个%w占位符用来生成一个可以包裹Error的Wrapping Error。
err:=errors.News("报错信息")
w:=fmt.Errorf("包裹wrap %w",err)

printf

支持各种占位符。

占位符说明
%是字符串运算符,被称为格式化操作符。
%v值的默认格式表示
%+v类似%v,但输出结构体时会添加字段名
%#v值的Go语法表示
%t布尔值
%T打印值的类型
%%百分号
%b二进制表示
%c相应Unicode码点所表示的字符
%d十进制表示
%o八进制表示
%q单引号围绕的字符字面值,由Go语法安全地转义
%x十六进制表示,字母形式为小写 a-f
%X十六进制表示,字母形式为大写 A-F
%UUnicode格式:U+1234,等同于 "U+%04X"
%s字符串或切片的无解译字节
%q双引号围绕的字符串,由Go语法安全地转义
%x十六进制,小写字母,每字节两个字符
%X十六进制,大写字母,每字节两个字符
%p十六进制表示,前缀 0x

默认格式

类型占位符
bool:%t
int, int8 etc.:%d
uint, uint8 etc.:%d, %x if printed with %#v
float32, complex64, etc:%g
string:%s
chan:%p
pointer:%p

+总打印数值的正负号;对于%q(%+q)保证只输出ASCII编码的字符。

  • 左对齐

备用格式:为八进制添加前导 0(%#o),为十六进制添加前导 0x(%#x)或0X(%#X),为 %p(%#p)去掉前导 0x;对于 %q,若 strconv.CanBackquote 返回 true,就会打印原始(即反引号围绕的)字符串;如果是可打印字符,%U(%#U)会写出该字符的Unicode编码形式(如字符 x 会被打印成 U+0078 'x')。
' ' (空格)为数值中省略的正负号留出空白(% d);以十六进制(% x, % X)打印字符串或切片时,在字节之间用空格隔开
0 填充前导的0而非空格;对于数字,这会将填充移到正负号之后

p := point{1, 2}
    fmt.Printf("%v\n", p) //{1,2}
    fmt.Printf("%+v\n", p) //{x:1 y:2}
    fmt.Printf("%#v\n", p) //main.point{x:1, y:2}
    fmt.Printf("%T\n", p) // main.point
    fmt.Printf("%t\n", true) //true
    fmt.Printf("%d\n", 123) //123
    fmt.Printf("%b\n", 14) //1110
    fmt.Printf("%c\n", 33) //!
    fmt.Printf("%x\n", 456) //1c8
    fmt.Printf("%f\n", 78.9) //78.900000
    fmt.Printf("%e\n", 123400000.0) //1.234000e+08
    fmt.Printf("%E\n", 123400000.0) //1.234000E+08
    fmt.Printf("%s\n", "\"string\"") //"string"
    fmt.Printf("%q\n", "\"string\"")//"\"string\""
    fmt.Printf("%x\n", "hex this") //6865782074686973
    fmt.Printf("%p\n", &p) //0xc0000b4010
    fmt.Printf("|%6d|%6d|\n", 12, 345) //|    12|   345|
    fmt.Printf("|%6.2f|%6.2f|\n", 1.2, 3.45) //|  1.20|  3.45|
    fmt.Printf("|%-6.2f|%-6.2f|\n", 1.2, 3.45) //|1.20  |3.45  |
    fmt.Printf("|%6s|%6s|\n", "foo", "b") //|   foo|     b|
    fmt.Printf("|%-6s|%-6s|\n", "foo", "b") //|foo   |b     |
    s := fmt.Sprintf("a %s", "string") 
    fmt.Println(s) //a string
    fmt.Fprintf(os.Stderr, "an %s\n", "error")//an error

宽度标识符

宽度通过一个紧跟在百分号后面的十进制数指定,如果未指定宽度,则表示值时除必需之外不作填充。精度通过(可选的)宽度后跟点号后跟的十进制数指定。如果未指定精度,会使用默认精度;如果点号后没有跟数字,表示精度为0。

占位符 说明
%f 默认宽度,默认精度
%9f 宽度9,默认精度
%.2f 默认宽度,精度2
%9.2f 宽度9,精度2
%9.f 宽度9,精度0

获取输出
Go语言fmt包下有fmt.Scan、fmt.Scanf、fmt.Scanln三个函数,可以在程序运行过程中从标准输入获取用户的输入。

fmt.Scan

Scan从标准输入扫描文本,读取由空白符分隔的值保存到传递给本函数的参数中,换行符视为空白符。
本函数返回成功扫描的数据个数和遇到的任何错误。如果读取的数据个数比提供的参数少,会返回一个错误报告原因。

fmt.Scan从标准输入中扫描用户输入的数据,将以空白符分隔的数据分别存入指定的参数。

fmt.Scanf

Scanf从标准输入扫描文本,根据format参数指定的格式去读取由空白符分隔的值保存到传递给本函数的参数中。
本函数返回成功扫描的数据个数和遇到的任何错误。

fmt.Scanf不同于fmt.Scan简单的以空格作为输入数据的分隔符,fmt.Scanf为输入数据指定了具体的输入内容格式,只有按照格式输入数据才会被扫描并存入对应变量。

fmt.Scanln

Scanln类似Scan,它在遇到换行时才停止扫描。最后一个数据后面必须有换行或者到达结束位置。
本函数返回成功扫描的数据个数和遇到的任何错误。

fmt.Scanln遇到回车就结束扫描了,这个比较常用

几种输入方式的区别

输出方式区别
Scan、Scanf 和 Scanln从os.Stdin 中读取;
Fscan、Fscanf 和 Fscanln从指定的 io.Reader 中读取;
Sscan、Sscanf 和 Sscanln从实参字符串中读取。
Scanln、Fscanln 和 Sscanln在换行符处停止扫描,且需要条目紧随换行符之后;
Scanf、Fscanf 和 Sscanf需要输入换行符来匹配格式中的换行符;其它函数则将换行符视为空格。

bufio.NewReader

func bufioDemo() {
reader := bufio.NewReader(os.Stdin) // 从标准输入生成读对象
fmt.Print("请输入内容:")
text, _ := reader.ReadString('\n') // 读到换行
text = strings.TrimSpace(text)
fmt.Printf("%#v\n", text)
}

Fscan系列

fmt.Scan、fmt.Scanf、fmt.Scanln三个函数,只不过它们不是从标准输入中读取数据而是从io.Reader中读取数据。

Sscan系列

fmt.Scan、fmt.Scanf、fmt.Scanln三个函数,只不过它们不是从标准输入中读取数据而是从指定字符串中读取数据。

查看原文

赞 0 收藏 0 评论 0

认证与成就

  • 认证信息 前端工程师
  • 获得 150 次点赞
  • 获得 2 枚徽章 获得 0 枚金徽章, 获得 0 枚银徽章, 获得 2 枚铜徽章

擅长技能
编辑

开源项目 & 著作
编辑

注册于 2019-04-29
个人主页被 2.1k 人浏览