力扣刷题(二)


title: golang力扣刷题(二)
date: 2021-11-04 10:06:27
categories:

  • go
    tags:
  • 基础

力扣刷题(二)

力扣刷题 全部题目模块(30~60)

简单

搜索插入位置

给定一个排序数组和一个目标值,在数组中找到目标值,并返回其索引。如果目标值不存在于数组中,返回它将会被按顺序插入的位置。

请必须使用时间复杂度为 O(log n) 的算法。

示例 1:
输入: nums = [1,3,5,6], target = 5
输出: 2
func searchInsert(nums []int, target int) int {
	i := 0
	j := len(nums) - 1
	c := -1
	for t := (i + j) / 2; i <= j; t = (i + j) / 2 {//二分法查找
		if nums[t] == target {    //相等输出
			c = t
			break
		}
		if nums[t] < target {     //缩小范围
			i = t + 1
		}
		if nums[t] > target {
			j = t - 1
		}
	}
	if j < 0 {               //排除最左端
		c = 0
	} else if i > len(nums)-1 {    //排除最右端
		c = len(nums)
	} else if nums[i] > target && target > nums[j] {   //中间端
		c = i
	}
	return c
}
执行用时:0 ms, 在所有 Go 提交中击败了100.00%的用户
内存消耗:3 MB, 在所有 Go 提交中击败了28.29%的用户

最后一个单词的长度

给你一个字符串 s,由若干单词组成,单词前后用一些空格字符隔开。返回字符串中 最后一个 单词的长度。

单词 是指仅由字母组成、不包含任何空格字符的最大子字符串。

示例 1:
输入:s = "Hello World"
输出:5
解释:最后一个单词是“World”,长度为5。
func lengthOfLastWord(s string) int {
	n := 0         //记录长度
	a := 0         //计数器
	for _, m := range s {     //遍历字符串
		if m == 32 {         //如果为空  a清0
			a = 0
		} else {           //不为空 a++
			a++
		}
		if a != 0 {          //如果a不是空,则n跟着a增加
			n = a
		}
	}
	return n
}
执行用时:0 ms, 在所有 Go 提交中击败了100.00%的用户
内存消耗:2 MB, 在所有 Go 提交中击败了89.55%的用户

最大子数组和

给你一个整数数组 nums ,请你找出一个具有最大和的连续子数组(子数组最少包含一个元素),返回其最大和。

子数组 是数组中的一个连续部分。

示例 1:
输入:nums = [-2,1,-3,4,-1,2,1,-5,4]
输出:6
解释:连续子数组 [4,-1,2,1] 的和最大,为 6 。
示例 2:
输入:nums = [1]
输出:1
func maxSubArray(nums []int) int {
	max := nums[0]    //max 计数
	for i := 1; i < len(nums); i++ {
		if nums[i]+nums[i-1] > nums[i] {
			nums[i] = nums[i] + nums[i-1]  //更新i  记录最大值
		}
		if nums[i] > max {    //更新最大值
			max = nums[i]
		}
	}
	return max
}
执行用时:72 ms, 在所有 Go 提交中击败了99.93%的用户
内存消耗:9.3 MB, 在所有 Go 提交中击败了37.27%的用户

回文链表

给定一个链表的 头节点 head **,**请判断其是否为回文链表。

如果一个链表是回文,那么链表节点序列从前往后看和从后往前看是相同的。

输入: head = [1,2,3,3,2,1]
输出: true
func reverselist(head *ListNode) (l *ListNode, r *ListNode) {
	var p, q, m *ListNode //翻转函数,输入123,返回321 的头尾指针
	p = head
	q = head.Next
	m = q.Next
	if m == nil {
		q.Next = p
		p.Next = nil
		return q, p
	}
	for q != nil {
		q.Next = p
		p = q
		q = m
		if m.Next != nil {
			m = m.Next
		} else {
			q.Next = p
			break
		}
	}
	head.Next = nil
	return q, head
}
func isPalindrome(head *ListNode) bool {
	n := 1
	head1 := head
	head2 := head
	for head1.Next != nil {  //算出链表长度
		n++
		head1 = head1.Next
	}
	print(n)
	for i := 0; i < n/2; i++ {  //找到后面链表的开头
		head2 = head2.Next
		print(i)
	}
	if n > 1 && n%2 == 0 && n < 6 { //n=2,4  //排除前五个
		if n == 2 {
			if head.Val != head.Next.Val {
				return false
			}
		}
		if n == 4 {
			if head.Next.Val != head2.Val {
				return false
			}
			if head.Val != head2.Next.Val {
				return false
			}
		}
	}
	if n > 1 && n%2 == 1 && n < 6 { //n=3,5
		if n == 3 {
			if head.Val != head.Next.Next.Val {
				return false
			}
		}
		if n == 5 {
			head2 = head2.Next
			if head.Next.Val != head2.Val {
				return false
			}
			if head.Val != head2.Next.Val {
				return false
			}
		}
	}
	if n > 5 && n%2 == 0 { //偶数  大于6的时候 
		head3, _ := reverselist(head2)   //翻转后面链表,逐个对比
		print(head3.Val)
		for head3 != nil {
			if head.Val == head3.Val {
				head = head.Next
				head3 = head3.Next
			} else {
				return false
			}
		}
	}
	if n>5&&n%2==1 { //奇数 大于6的时候
		head2 = head2.Next
		head3, _ := reverselist(head2)//翻转后面链表,逐个对比  
		for head3 != nil {
			if head.Val == head3.Val {
				head = head.Next
				head3 = head3.Next
			} else {
				return false
			}
		}
	}
	return true
}

//这个太笨了 史上最lou代码
执行用时: 224 ms
内存消耗: 9.4 MB
func isPalindrome(head *ListNode) bool {
	head1 := head
	head2 := head
	var p, q *ListNode
	for head1 != nil && head1.Next != nil { //翻转前部分
		head1 = head1.Next.Next
		q = head2.Next
		head2.Next = p
		p = head2
		head2 = q
	}
	if head1 != nil {  //看他是不是奇数
		head2 = head2.Next
	}
	for p != nil {     //逐个对比
		if p.Val != head2.Val {
			return false
		}
		p = p.Next
		head2 = head2.Next
	}
	return true
}
执行用时:128 ms, 在所有 Go 提交中击败了90.49%的用户
内存消耗:10.9 MB, 在所有 Go 提交中击败了21.61%的用户
func isPalindrome(head *ListNode) bool {//递归
	var spalin func(*ListNode) bool
	spalin = func(head1 *ListNode) bool {
		if head1 != nil {
			if spalin(head1.Next) == false {
				return false
			}
			if head.Val != head1.Val {
				return false
			}
			head = head.Next
		}
		return true
	}
	return spalin(head)
}
执行用时: 164 ms
内存消耗: 17.6 MB

中等

下一个排列

实现获取 下一个排列 的函数,算法需要将给定数字序列重新排列成字典序中下一个更大的排列(即,组合出下一个更大的整数)。

如果不存在下一个更大的排列,则将数字重新排列成最小的排列(即升序排列)。

必须 原地 修改,只允许使用额外常数空间。

示例 1:
输入:nums = [1,2,3]
输出:[1,3,2]
示例 2:
输入:nums = [3,2,1]
输出:[1,2,3]
func nextPermutation(nums []int) []int {
	b := 0
	for i := len(nums) - 1; i > 0; i-- {     //从后往前遍历
		if nums[i] > nums[i-1] {               //如果比前一个大
			  a := 0 
				num := nums[i:]                    //截取切片
				sort.Ints(num)                     //升序排列
				for n := 0; n < len(num); n++ {    //遍历这个排列找到比它大的最小值
					if num[n] > nums[i-1] {
						a = nums[i-1]                  //交换位置
						nums[i-1] = num[n]
						num[n] = a
						break
					}
				}
				sort.Ints(num)                     //后面的再进行升序
				for j := 0; j < len(num); j++ {    //插入原来的数组
					nums[i] = num[j]
					i++
				}
				break                              //返回
		} else {                               //如果不大于前一个数 计数
			b++ 
		}
	}
	if b == len(nums)-1 {                    //计数等于数组长度 则全是降序
		nums = sort.Ints(nums)                   //将它生序
	}
	return nums
}

执行用时:0 ms, 在所有 Go 提交中击败了100.00%的用户
内存消耗:2.5 MB, 在所有 Go 提交中击败了15.16%的用户
func isPalindrome(head *ListNode) bool {//递归
	var spalin func(*ListNode) bool
	spalin = func(head1 *ListNode) bool {
		if head1 != nil {
			if spalin(head1.Next) == false {
				return false
			}
			if head.Val != head1.Val {
				return false
			}
			head = head.Next
		}
		return true
	}
	return spalin(head)
}
执行用时:164 ms, 在所有 Go 提交中击败了14.99%的用户
内存消耗:17.6 MB, 在所有 Go 提交中击败了5.19%的用户

搜索旋转排序数组

整数数组 nums 按升序排列,数组中的值 互不相同 。

在传递给函数之前,nums 在预先未知的某个下标 k(0 <= k < nums.length)上进行了 旋转,使数组变为 [nums[k], nums[k+1], …, nums[n-1], nums[0], nums[1], …, nums[k-1]](下标 从 0 开始 计数)。例如, [0,1,2,4,5,6,7] 在下标 3 处经旋转后可能变为 [4,5,6,7,0,1,2] 。

给你 旋转后 的数组 nums 和一个整数 target ,如果 nums 中存在这个目标值 target ,则返回它的下标,否则返回 -1 。

示例 1:
输入:nums = [4,5,6,7,0,1,2], target = 0
输出:4
func search(nums []int, target int) int {
	if len(nums) >= 2 {  //>=2的时候
		l := 0
		r := len(nums) - 1      //分别指向首尾
		for l <= r {
			i := (l + r) / 2
			if nums[i] == target {    //找到返回
				return i
			}
			if nums[0] <= nums[i] {      //前半部分部分
				if nums[0] <= target && target < nums[i] {
					r = i - 1
				} else {
					l = i + 1
				}
			} else {
				if nums[i] < target && target <= nums[len(nums)-1] {
					l = i + 1
				} else {
					r = i - 1
				}
			}
		}
	} else { //如果只有一个或0个的时候
		if len(nums) == 1 && nums[0] == target {
			return 0
		} else {
			return -1
		}
	}
	return -1
}
执行用时:0 ms, 在所有 Go 提交中击败了100.00%的用户
内存消耗:2.5 MB, 在所有 Go 提交中击败了100.00%的用户

在排序数组中查找元素的第一个和最后一个位置

给定一个按照升序排列的整数数组 nums,和一个目标值 target。找出给定目标值在数组中的开始位置和结束位置。

如果数组中不存在目标值 target,返回 [-1, -1]。

进阶:

你可以设计并实现时间复杂度为 O(log n) 的算法解决此问题吗?

示例 1:
输入:nums = [5,7,7,8,8,10], target = 8
输出:[3,4]

在排序数组中查找元素的第一个和最后一个位置

给定一个按照升序排列的整数数组 nums,和一个目标值 target。找出给定目标值在数组中的开始位置和结束位置。

如果数组中不存在目标值 target,返回 [-1, -1]。

进阶:

你可以设计并实现时间复杂度为 O(log n) 的算法解决此问题吗?

示例 1:
输入:nums = [5,7,7,8,8,10], target = 8
输出:[3,4]
func searchRange(nums []int, target int) []int {
	l := sort.SearchInts(nums, target)    //找出这个数并返回下标
	if l == len(nums) || nums[l] != target {
		return []int{-1, -1}
	}
	r := sort.SearchInts(nums, target + 1) - 1 //找出比他大的数返回下标 减1
	return []int{l, r}
}
执行用时:8 ms, 在所有 Go 提交中击败了40.01%的用户
内存消耗:3.9 MB, 在所有 Go 提交中击败了59.36%的用户

有效的数独

请你判断一个 9x9 的数独是否有效。只需要 根据以下规则 ,验证已经填入的数字是否有效即可。

数字 1-9 在每一行只能出现一次。
数字 1-9 在每一列只能出现一次。
数字 1-9 在每一个以粗实线分隔的 3x3 宫内只能出现一次。(请参考示例图)
数独部分空格内已填入了数字,空白格用 ‘.’ 表示。

注意:

一个有效的数独(部分已被填充)不一定是可解的。
只需要根据以上规则,验证已经填入的数字是否有效即可。

func isValidSudoku(board [][]byte) bool {
	for i := 0; i < 9; i++ { //检查每行每列
		for j := 0; j < 8; j++ {
			a := board[i][j]
			b := board[j][i]
			for k := j + 1; k < 9; k++ {
				if a == board[i][k] && a != 46 { //行
					return false
				}
				if b == board[k][i] && b != 46 { //列
					return false
				}
			}
		}
		for j := 0; j < 9; j++ {            //检查每个小方块
			for k := i + 1; k%3 != 0; k++ {   //直接从下一行检查  
				for h := j / 3 * 3; h < j/3*3+3; h++ {
					if board[i][j] == board[k][h] && board[i][j] != 46 {
						return false
					}
				}
			}
		}
	}
	return true
}
执行用时:4 ms, 在所有 Go 提交中击败了60.38%的用户
内存消耗:2.6 MB, 在所有 Go 提交中击败了71.78%的用户

外观数列

给定一个正整数 n ,输出外观数列的第 n 项。

「外观数列」是一个整数序列,从数字 1 开始,序列中的每一项都是对前一项的描述。

你可以将其视作是由递归公式定义的数字字符串序列:

countAndSay(1) = “1”
countAndSay(n) 是对 countAndSay(n-1) 的描述,然后转换成另一个数字字符串。
前五项如下:

1.     1
2.     11
3.     21
4.     1211
5.     111221

第一项是数字 1
描述前一项,这个数是 1 即 “ 一 个 1 ”,记作 “11”
描述前一项,这个数是 11 即 “ 二 个 1 ” ,记作 “21”
描述前一项,这个数是 21 即 “ 一 个 2 + 一 个 1 ” ,记作 “1211”
描述前一项,这个数是 1211 即 “ 一 个 1 + 一 个 2 + 二 个 1 ” ,记作 “111221”
要 描述 一个数字字符串,首先要将字符串分割为 最小 数量的组,每个组都由连续的最多 相同字符 组成。然后对于每个组,先描述字符的数量,然后描述字符,形成一个描述组。要将描述转换为数字字符串,先将每组中的字符数量用数字替换,再将所有描述组连接起来。

func countAndSay(n int) string {
	  s := make([]rune, 0)
	  c := '1'
		s = append(s, c)
		for i := 1; i < n; i++ {   //n==1直接输出,大于1循环
			d := s[0]                 //d==第一个字节
			s2 := make([]rune, 0)
			for a, b := range s {      //遍历s
				if a == 0 {              //去掉第一个重复的
					continue
				}
				if d != b {               //遇到不一样的
					s2 = append(s2, c, d)   //将之前的加入
					d = b                   //d改成现在的b
					c = '1'                 //		计数改为1
				} else {                  //遇到一样的 C++
					c++
				}
			}
			s2 = append(s2, c, d)        //将最后的结果加入
			s = s2
			c = '1'                      //c计数改为1
		}
		return string(s)
}
执行用时:216 ms, 在所有 Go 提交中击败了14.13%的用户
内存消耗:7.2 MB, 在所有 Go 提交中击败了46.46%的用户

组合总和

给定一个无重复元素的正整数数组 candidates 和一个正整数 target ,找出 candidates 中所有可以使数字和为目标数 target 的唯一组合。

candidates 中的数字可以无限制重复被选取。如果至少一个所选数字数量不同,则两种组合是唯一的。

对于给定的输入,保证和为 target 的唯一组合数少于 150 个。

示例 1:
输入: candidates = [2,3,6,7], target = 7
输出: [[7],[2,2,3]]
func combinationSum(candidates []int, target int) [][]int {
	sum := 0
	start := 0
	var s = make([][]int, 0)
	var s1 = make([]int, 0)
	var combination func(candidates []int, target int, sum int, start int)   //定义内置函数  将两个函数分开会出错,不是函数本身错误 它系统有问题过不去
	combination = func(candidates []int, target int, sum int, start int) {
		if sum == target {  //如果和与target相等 
			t := make([]int, len(s1)) //切片只是一个指向基础数组的指针,必须复制
			copy(t, s1)       //如果不希望影响其他切片,需要创建切片副本
			s = append(s, t)   //插入正确答案
			return
		}
		for i := start; i < len(candidates); i++ {
			if sum > target {  //剪枝,大于 终止循环
				break
			}
			s1 = append(s1, candidates[i])  //插入数组
			sum = sum + candidates[i]       //求和
			combination(candidates, target, sum, i)    //回溯
			sum = sum - candidates[i]       //撤销操作
			s1 = s1[:len(s1)-1]
		}
	}
	combination(candidates, target, sum, start)
	return s
}
执行用时:0 ms, 在所有 Go 提交中击败了100.00%的用户
内存消耗:2.7 MB, 在所有 Go 提交中击败了98.66%的用户

组合总和II

给定一个数组 candidates 和一个目标数 target ,找出 candidates 中所有可以使数字和为 target 的组合。

candidates 中的每个数字在每个组合中只能使用一次。

注意:解集不能包含重复的组合。

示例 1:
输入: candidates = [10,1,2,7,6,1,5], target = 8,
输出:
[
[1,1,6],
[1,2,5],
[1,7],
[2,6]
]
func combinationSum2(candidates []int, target int) [][]int {
	sort.Ints(candidates) //排序
	var s = make([][]int, 0)     //最终输出数组
	var s1 = make([]int, 0)     //单个记录答案数组
	vis := make([]bool, len(candidates))   //一个标记数组,去重
	sum := 0             //和
	star := 0           //candidates开始下标
	var combin func(candidates []int, target int, sum int, star int)
	combin = func(candidates []int, target int, sum int, star int) {
    //根据上个题的经验 将回溯函数建立在函数内部
		if sum == target {      //如何和相等
			t := make([]int, len(s1))       //新建答案数组 复制插入,切片是指针
			copy(t, s1)
			s = append(s, t)
			return
		}
		for i := star; i < len(candidates); i++ {  //从开始下标遍历
			if sum > target {               //大于  剪枝,后面不用遍历
				break
			}
    // vis[i - 1] == true,说明同一树支candidates[i - 1]使用过
    // vis[i - 1] == false,说明同一树层candidates[i - 1]使用过
    // 要对同一树层使用过的元素进行跳过
			if i > 0 && candidates[i] == candidates[i-1] && !vis[i-1] {
				continue   //去重
      }
			vis[i] = true
			sum = sum + candidates[i]
			s1 = append(s1, candidates[i])
			combin(candidates, target, sum, i+1)   //回溯
			sum = sum - candidates[i]
			s1 = s1[:len(s1)-1]
			vis[i] = false
		}
	}
	combin(candidates, target, sum, star)
	return s
}
执行用时:4 ms, 在所有 Go 提交中击败了45.08%的用户
内存消耗:2.5 MB, 在所有 Go 提交中击败了88.90%的用户

字符串相乘

给定两个以字符串形式表示的非负整数 num1 和 num2,返回 num1 和 num2 的乘积,它们的乘积也表示为字符串形式。

注意:不能使用任何内置的 BigInteger 库或直接将输入转换为整数。

示例 1:

输入: num1 = "2", num2 = "3"
输出: "6"

示例 2:

输入: num1 = "123", num2 = "456"
输出: "56088"
func multiply(num1 string, num2 string) string {
    if num1 == "0" || num2 == "0" {
        return "0"
    }
    ans := "0"
    m, n := len(num1), len(num2)
    for i := n - 1; i >= 0; i-- {
        curr := ""
        add := 0
        for j := n - 1; j > i; j-- {//字符串移位加0
            curr += "0"
        }
        y := int(num2[i] - '0')
        for j := m - 1; j >= 0; j-- {
            x := int(num1[j] - '0')
            product := x * y + add
            curr = strconv.Itoa(product % 10) + curr
            add = product / 10
        }
        for ; add != 0; add /= 10 {
            curr = strconv.Itoa(add % 10) + curr
        }
        ans = addStrings(ans, curr)
    }
    return ans
}

func addStrings(num1, num2 string) string {
    i, j := len(num1) - 1, len(num2) - 1
    add := 0
    ans := ""
    for ; i >= 0 || j >= 0 || add != 0; i, j = i - 1, j - 1 {
        x, y := 0, 0
        if i >= 0 {
            x = int(num1[i] - '0')
        }
        if j >= 0 {
            y = int(num2[j] - '0')
        }
        result := x + y + add
        ans = strconv.Itoa(result % 10) + ans
        add = result / 10
    }
    return ans
}
执行用时:44 ms, 在所有 Go 提交中击败了9.51%的用户
内存消耗:6.7 MB, 在所有 Go 提交中击败了21.60%的用户

跳跃游戏2

给你一个非负整数数组 nums ,你最初位于数组的第一个位置。

数组中的每个元素代表你在该位置可以跳跃的最大长度。

你的目标是使用最少的跳跃次数到达数组的最后一个位置。

假设你总是可以到达数组的最后一个位置。

示例 1:
输入: nums = [2,3,1,1,4]
输出: 2
解释: 跳到最后一个位置的最小跳跃数是 2。
     从下标为 0 跳到下标为 1 的位置,跳 1 步,然后跳 3 步到达数组的最后一个位置。
示例 2:
输入: nums = [2,3,0,1,4]
输出: 2
func jump(nums []int) int { //创建一个切片记录
	m := len(nums)
	n1:=0
	a:=0
	num:=make([]int,m)
	for i:=0;i<m;i++{
		n2:=i+nums[i]    //本次能挑到的最远值
		if n2>n1{   //如果比n1大 则换值
			n1=n2
			a=num[i]+1  //a++  为了确保不出错 从num[i]上加
		}
		for i:=1;i<=n1&&i<m;i++{ //更新这个切片  防止越界 加上i<m
			if num[i]==0{  //如果里面没有值 则加上a
				num[i]=a
			}
		}
	}
	return num[m-1]   //最后输出最后记录值
}
执行用时:236 ms, 在所有 Go 提交中击败了5.04%的用户
内存消耗:6.1 MB, 在所有 Go 提交中击败了27.96%的用户
func jump(nums []int) int {
	m := len(nums)
	n1 := 0
	a := 0    //记录跳跃次数
	max := 0   //记录边界
	for i := 0; i < m-1; i++ {   //i<m-1可防止只有一个值时 程序执行for循环
		n2 := i + nums[i]   //最远值
		if n2 > n1 {       //找到跳的最大值
			n1 = n2 
		}
		if i == max {     //到达边界
			max = n1       //边界等于最大值
			a++            //步数+1
		}
	}
	return a
}
执行用时:20 ms, 在所有 Go 提交中击败了35.90%的用户
内存消耗:5.8 MB, 在所有 Go 提交中击败了53.87%的用户

全排列

给定一个不含重复数字的数组 nums ,返回其 所有可能的全排列 。你可以 按任意顺序 返回答案。

示例 1:
输入:nums = [1,2,3]
输出:[[1,2,3],[1,3,2],[2,1,3],[2,3,1],[3,1,2],[3,2,1]]
示例 2:
输入:nums = [0,1]
输出:[[0,1],[1,0]]
示例 3:
输入:nums = [1]
输出:[[1]]

func permute(nums []int) [][]int {
	n := len(nums)
	num := make([][]int, 0)
	var backtrace func(path int)  //内置循环函数
	backtrace = func(path int) {
		if path == n {              //深度等于n 输出
			nu := make([]int, n)
			copy(nu, nums)             //不然会全部改变
			num = append(num, nu)
			return
		}
		for i := path; i < n; i++ {
			nums[path], nums[i] = nums[i], nums[path]   //交换位置
			backtrace(path + 1)                           //递归
			nums[path], nums[i] = nums[i], nums[path]     //撤销交换
		}
	}
	backtrace(0)
	return num
}
执行用时:0 ms, 在所有 Go 提交中击败了100.00%的用户
内存消耗:2.4 MB, 在所有 Go 提交中击败了99.60%的用户


func permute(nums []int) [][]int {
    if len(nums) == 0 {
        return nil
    }
    //思路是在已有的排列数组中,从头到尾见缝插针,组成新的全排列
    //比如有 1,2 的情况下,插入3,就是在头插入 3,1,2;中间插入1,3,2;尾巴插入1,2,3
    temp := make([][]int,0)
    temp = append(temp,[]int{nums[0]})
    for i:=1;i<len(nums);i++{
        temp2 := temp
        temp = make([][]int,0)
        for j:=0;j<=i;j++{
            for k:=0;k<len(temp2);k++ {
                temp3 := make([]int, 0)
                temp3 = append(temp3, temp2[k][0:j]...)
                temp3 = append(temp3, nums[i])
                temp3 = append(temp3, temp2[k][j:]...)
                temp = append(temp, temp3)
            }
        }
    }
    return temp
}

全排列2

给定一个可包含重复数字的序列 nums ,按任意顺序 返回所有不重复的全排列。

示例 1:
输入:nums = [1,1,2]
输出:
[[1,1,2],
 [1,2,1],
 [2,1,1]]
示例 2:
输入:nums = [1,2,3]
输出:[[1,2,3],[1,3,2],[2,1,3],[2,3,1],[3,1,2],[3,2,1]]

旋转图像

给定一个 n × n 的二维矩阵 matrix 表示一个图像。请你将图像顺时针旋转 90 度。

你必须在 原地 旋转图像,这意味着你需要直接修改输入的二维矩阵。请不要 使用另一个矩阵来旋转图像。

输入:matrix = [[1,2,3],[4,5,6],[7,8,9]]
输出:[[7,4,1],[8,5,2],[9,6,3]]】
func rotate(matrix [][]int) {  //有点绕 背答案吧
    n := len(matrix)
    for i := 0; i < n/2; i++ {
        for j := 0; j < (n+1)/2; j++ {
            matrix[i][j], matrix[n-j-1][i], matrix[n-i-1][n-j-1], matrix[j][n-i-1] =
                matrix[n-j-1][i], matrix[n-i-1][n-j-1], matrix[j][n-i-1], matrix[i][j]
        }
    }
}

执行用时:0 ms, 在所有 Go 提交中击败了100.00%的用户
内存消耗:2.1 MB, 在所有 Go 提交中击败了100.00%的用户

字母异位词分组

给你一个字符串数组,请你将 字母异位词 组合在一起。可以按任意顺序返回结果列表。

字母异位词 是由重新排列源单词的字母得到的一个新单词,所有源单词中的字母通常恰好只用一次。

示例 1:
输入: strs = ["eat", "tea", "tan", "ate", "nat", "bat"]
输出: [["bat"],["nat","tan"],["ate","eat","tea"]]
示例 2:
输入: strs = [""]
输出: [[""]]
func SortString(s string) string { //排序函数
	ss := make([]rune, 0)
	for _, n := range s {
		ss = append(ss, n)
	}
	for i := 0; i < len(ss); i++ {
		for j := i + 1; j < len(ss); j++ {
			if ss[i] > ss[j] {
				a := ss[i]
				ss[i] = ss[j]
				ss[j] = a
			}
		}
	}
	return string(ss)
}
func groupAnagrams(strs []string) [][]string {
	mp := map[string][]string{} //建立一个字典
	for _, str := range strs {  //遍历字符串数组
		ss := SortString(str)      //排序
		mp[ss] = append(mp[ss], str)   //加入字典 
	}
	ans := make([][]string, 0, len(mp))  
	for _, v := range mp {  //将字典中的数据加入二维数组
		ans = append(ans, v)
	}
	return ans
}
执行用时:24 ms, 在所有 Go 提交中击败了54.24%的用户
内存消耗:7.9 MB, 在所有 Go 提交中击败了71.81%的用户

Pow(x,n)

实现 pow(x, n) ,即计算 x 的 n 次幂函数(即,xn )。

示例 1:
输入:x = 2.00000, n = 10
输出:1024.00000
示例 2:
输入:x = 2.10000, n = 3
输出:9.26100
func Pow(x float64, n int) float64 {  //精髓在这里 2^0 2^1 2^2 2^4 2^8
	if n == 0 {                         //不然会超时
		return 1
	}
	y := Pow(x, n/2)
	if n%2 == 0 {
		return y * y
	}
	return y * y * x
}
func myPow(x float64, n int) float64 {
	if n > 0 {
		if x < 0 {
			if n%2 == 1 {
				x = -Pow(-x, n)
			} else {
				x = Pow(-x, n)
			}
		} else {
			x = Pow(x, n)
		}
	} else if n == 0 {
		return 1.0
	} else { //n<0
		if x < 0 {
			if (-n)%2 == 1 {
				x = -Pow(-x, -n)
			} else {
				x = Pow(-x, -n)
			}
		} else {
			x = (1 / Pow(x, -n))
		}
	}
	return x
}

func myPow(x float64, n int) float64 {  //最后结果跟x正负没有关系
	if n > 0 {
		x = Pow(x, n)
	} else if n == 0 {
		return 1.0
	} else { //n<0
		x = (1 / Pow(x, -n))
	}
	return x
}
执行用时:0 ms, 在所有 Go 提交中击败了100.00%的用户
内存消耗:1.9 MB, 在所有 Go 提交中击败了86.38%的用户

螺旋矩阵

给你一个 mn 列的矩阵 matrix ,请按照 顺时针螺旋顺序 ,返回矩阵中的所有元素。

输入:matrix = [[1,2,3],[4,5,6],[7,8,9]]
输出:[1,2,3,6,9,8,7,4,5]
func spiralOrder(matrix [][]int) []int {
	m := len(matrix)
	n := len(matrix[0])
	s := make([]int, 0)
	if m == 1 {  //处理只有一行
		for i := 0; i < n; i++ {
			s = append(s, matrix[0][i])
		}
	} else if n == 1 {//处理只有一列
		for i := 0; i < m; i++ {
			s = append(s, matrix[i][0])
		}
	} else {
		matrix2 := make([][]bool, m)
		for i := 0; i < m; i++ { //创建记录数组,默认为false
			matrix2[i] = make([]bool, n)
		}
		for i, j := 0, 0; i < m && j < n; {  //循环
			for j < n && matrix2[i][j] == false {  //遍历到尾部,向下
				s = append(s, matrix[i][j])
				matrix2[i][j] = true
				j++
			}
			if j == n || matrix2[i][j] == true { //到尾部,改i,j
				j--
				i++
			}
			for i < m && matrix2[i][j] == false { //向下遍历
				s = append(s, matrix[i][j])
				matrix2[i][j] = true
				i++
			}
			if i == m || matrix2[i][j] == true {//到底部,改i,j
				i--
				j--
			}
			for j > -1 && matrix2[i][j] == false {//向左遍历
				s = append(s, matrix[i][j])
				matrix2[i][j] = true
				j--
			}
			if j == -1 || matrix2[i][j] == true { //到左边,改i,j
				j++
				i--
			}
			for i > -1 && matrix2[i][j] == false {//向上遍历
				s = append(s, matrix[i][j])
				matrix2[i][j] = true
				i--
			}
			if i == 0 || matrix2[i][j] == true {//到顶部,改i,j
				i++
				j++
				if matrix2[i][j] == true {    //设置结束条件
					break
				}
			}
		}
	}
	return s
}
执行用时:0 ms, 在所有 Go 提交中击败了100.00%的用户
内存消耗:1.9 MB, 在所有 Go 提交中击败了77.39%的用户

跳跃游戏

给定一个非负整数数组 nums ,你最初位于数组的 第一个下标 。

数组中的每个元素代表你在该位置可以跳跃的最大长度。

判断你是否能够到达最后一个下标。

示例 1:
输入:nums = [2,3,1,1,4]
输出:true
解释:可以先跳 1 步,从下标 0 到达下标 1, 然后再从下标 1 跳 3 步到达最后一个下标。
示例 2:
输入:nums = [3,2,1,0,4]
输出:false
解释:无论怎样,总会到达下标为 3 的位置。但该下标的最大跳跃长度是 0 , 所以永远不可能到达最后一个下标。
func canJump(nums []int) bool {
    n:=len(nums)
    boundary:=0  //设置边界
    for i:=0;i<n;i++{
        if (i+nums[i])>boundary{  
            boundary=i+nums[i]   //更新边界
        }
        if nums[i]==0&&n>1&&i>=boundary{  //去除[0][0,1][3,0,4]
            return false
        }
        if boundary>=n-1{  //边界超出 true
             return true
        }
    }
    return false
}
执行用时:52 ms, 在所有 Go 提交中击败了74.87%的用户
内存消耗:6.7 MB, 在所有 Go 提交中击败了75.06%的用户

合并区间

以数组 intervals 表示若干个区间的集合,其中单个区间为 intervals[i] = [starti, endi] 。请你合并所有重叠的区间,并返回 一个不重叠的区间数组,该数组需恰好覆盖输入中的所有区间 。

示例 1:
输入:intervals = [[1,3],[2,6],[8,10],[15,18]]
输出:[[1,6],[8,10],[15,18]]
解释:区间 [1,3] 和 [2,6] 重叠, 将它们合并为 [1,6].
示例 2:
输入:intervals = [[1,4],[4,5]]
输出:[[1,5]]
解释:区间 [1,4] 和 [4,5] 可被视为重叠区间。
func merge(intervals [][]int) [][]int {
	for i := 0; i < len(intervals); i++ {   //先从第一个值开始排序  不排序搞不了,试过了
		for j := i + 1; j < len(intervals); j++ {
			if intervals[i][0] > intervals[j][0] {
				a := intervals[i][0]
				b := intervals[i][1]
				intervals[i][0] = intervals[j][0]
				intervals[i][1] = intervals[j][1]
				intervals[j][0] = a
				intervals[j][1] = b
			}
		}
	}
	
	for i := 0; i < len(intervals);  {
		if i+1 < len(intervals)&& intervals[i][1] <= intervals[i+1][1]&&intervals[i][1]>=intervals[i+1][0] {//[a,b][c,d] d>=b>=c 时
			intervals[i][1] = intervals[i+1][1] //b=d
			intervals = append(intervals[:i+1], intervals[i+2:]...)  //去掉后面的
			i=0
		} else{
			if i+1 < len(intervals)&& intervals[i][1] > intervals[i+1][1] {//b>d时
				intervals = append(intervals[:i+1], intervals[i+2:]...) //去掉后面的
				i=0
			}else{
                i++  //i++
            }
		}
	}
	return intervals
}

插入区间

给你一个 无重叠的 ,按照区间起始端点排序的区间列表。

在列表中插入一个新的区间,你需要确保列表中的区间仍然有序且不重叠(如果有必要的话,可以合并区间)。

示例 1:
输入:intervals = [[1,3],[6,9]], newInterval = [2,5]
输出:[[1,5],[6,9]]
示例 2:
输入:intervals = [[1,2],[3,5],[6,7],[8,10],[12,16]], newInterval = [4,8]
输出:[[1,2],[3,10],[12,16]]
解释:这是因为新的区间 [4,8] 与 [3,5],[6,7],[8,10] 重叠。
//最笨方法
func merge(intervals [][]int) [][]int {
	for i := 0; i < len(intervals); i++ { //先从第一个值开始排序  不排序搞不了,试过了
		for j := i + 1; j < len(intervals); j++ {
			if intervals[i][0] > intervals[j][0] {
				a := intervals[i][0]
				b := intervals[i][1]
				intervals[i][0] = intervals[j][0]
				intervals[i][1] = intervals[j][1]
				intervals[j][0] = a
				intervals[j][1] = b
			}
		}
	}

	for i := 0; i < len(intervals); {
		if i+1 < len(intervals) && intervals[i][1] <= intervals[i+1][1] && intervals[i][1] >= intervals[i+1][0] { //[a,b][c,d] d>=b>=c 时
			intervals[i][1] = intervals[i+1][1]                     //b=d
			intervals = append(intervals[:i+1], intervals[i+2:]...) //去掉后面的
			i = 0
		} else {
			if i+1 < len(intervals) && intervals[i][1] > intervals[i+1][1] { //b>d时
				intervals = append(intervals[:i+1], intervals[i+2:]...) //去掉后面的
				i = 0
			} else {
				i++ //i++
			}
		}
	}
	return intervals
}
func insert(intervals [][]int, newInterval []int) [][]int {
	if len(intervals) == 0 { //如果长度为零,直接加入输出
		intervals = append(intervals, newInterval)
	} else {  //直接插入 然后用上面函数重新排序 合并  最笨方法
		intervals = append(intervals, newInterval)
		intervals = merge(intervals)
	}
	return intervals
}
执行用时:92 ms, 在所有 Go 提交中击败了5.41%的用户
内存消耗:4.5 MB, 在所有 Go 提交中击败了95.68%的用户
func insert(intervals [][]int, newInterval []int) [][]int {
	ans := make([][]int, 0)
	acc := false //哨兵 插入变true
	for _, terval := range intervals {

		if newInterval[1] < terval[0] { //在左边 无交集
			if acc != true {
				ans = append(ans, newInterval) //先把newInterval插入 并做好标记
				acc = true
			}
			ans = append(ans, terval) //继续插入其他元素
		} else if newInterval[0] > terval[1] { //在右边 无交集
			ans = append(ans, terval) // 先插入 interval newInterval先放着
		} else { //有交集的情况  更改 newInterval值
			newInterval[0] = min(newInterval[0], terval[0])
			newInterval[1] = max(newInterval[1], terval[1])
		}
	}
	if acc != true { //如果遍历完还没插入  则加后面
		ans = append(ans, newInterval)
	}
	return ans
}
func min(a, b int) int {
	if a < b {
		return a
	}
	return b
}
func max(a, b int) int {
	if a > b {
		return a
	}
	return b
}
执行用时:8 ms, 在所有 Go 提交中击败了75.14%的用户
内存消耗:4.5 MB, 在所有 Go 提交中击败了83.78%的用户

螺旋矩阵2

给你一个正整数 n ,生成一个包含 1n2 所有元素,且元素按顺时针顺序螺旋排列的 n x n 正方形矩阵 matrix

输入:n = 3
输出:[[1,2,3],[8,9,4],[7,6,5]]

示例 2:

输入:n = 1
输出:[[1]]
func generateMatrix(n int) [][]int {
	made := make([][]int, 0)
	mm := make([]int, 0)
	for i := 0; i < n; i++ {  //创建数组
		mm = append(mm, 0)
	}
	for i := 0; i < n; i++ {   //创建二维数组 
		cc := make([]int, len(mm))  //这里要copy 不然会一起改变数字
		copy(cc, mm)
		made = append(made, cc)
	}
	if n == 1 {   //排除n==1的情况
		made[0][0] = 1
		return made
	}
	m := 1
	for i, j := 0, 0; m < n*n+1; {   //给出循环限定条件  让他一直转
		if made[i][j] != 0 {         //改变方向条件
			i++
			j++
		}
		for j < n-1 && made[i][j] == 0 {    //从左往右
			made[i][j] = m
			m++
			j++
		}
		if made[i][j] != 0 {        //改变方向
			j--
			i++
		}
		for i < n-1 && made[i][j] == 0 {    //从上往下
			made[i][j] = m
			m++
			i++
		}
		if made[i][j] != 0 {        //改变方向
			i--
			j--
		}
		for j > 0 && made[i][j] == 0 {    //从右往左
			made[i][j] = m
			m++
			j--
		}
		if made[i][j] != 0 {      //改变方向
			i--
			j++
		}
		for i > 0 && made[i][j] == 0 {     //从下往上
			made[i][j] = m
			m++
			i--
		}
	}
	return made
}

困难

最长有效括号

给你一个只包含 ‘(’ 和 ‘)’ 的字符串,找出最长有效(格式正确且连续)括号子串的长度。

示例 1:
输入:s = "(()"
输出:2
解释:最长有效括号子串是 "()"
type Stack struct {        //栈结构
	size int
	top  int
	data []int
}
func max(x, y int) int {    //输出最大值函数
	if x > y {
		return x
	}
	return y
}
func longestValidParentheses(s string) int {
	s1 := Stack{            //初始化栈
		size: len(s),
		top:  -1,
		data: make([]int, len(s)+1),
	}
	length := 0
	maxlength := 0
	s1.top = 0
	s1.data[s1.top] = -1       //里面输入-1
	for m, a := range s {      //遍历S
		if string(a) == "(" {        //(  入栈
			s1.top++
			s1.data[s1.top] = m
		} else {                 //) 先出栈
			s1.top--
			if s1.top == -1 {            //如果栈为空  把 m放进去 新的开始
				s1.top++
				s1.data[s1.top] = m
			} else {                     //栈不为空 得到length  上面输入-1的原因
				length = m - s1.data[s1.top]
				maxlength = max(length, maxlength)     //得到最大值
			}
		}
	}
	return maxlength
}
执行用时:0 ms, 在所有 Go 提交中击败了100.00%的用户
内存消耗:2.8 MB, 在所有 Go 提交中击败了83.89%的用户

解数独

编写一个程序,通过填充空格来解决数独问题。

数独的解法需 遵循如下规则:

数字 1-9 在每一行只能出现一次。
数字 1-9 在每一列只能出现一次。
数字 1-9 在每一个以粗实线分隔的 3x3 宫内只能出现一次。(请参考示例图)
数独部分空格内已填入了数字,空白格用 ‘.’ 表示。

func isvalid(row int, col int, k byte, borad [][]byte) bool {
	for i := 0; i < 9; i++ { //判断行是否重复
		if borad[row][i] == k {
			return false
		}
	}
	for j := 0; j < 9; j++ { //判断列是否重复
		if borad[j][col] == k {
			return false
		}
	}
	Row := (row / 3) * 3
	Col := (col / 3) * 3
	for i := Row; i < Row+3; i++ { //判断这个小方块是否重复
		for j := Col; j < Col+3; j++ {
			if borad[i][j] == k {
				return false
			}
		}
	}
	return true //都没有重复 返回true
}
func solve(board [][]byte) bool {
	for i := 0; i < 9; i++ {
		for j := 0; j < 9; j++ {
			if board[i][j] != '.' { //如果为数字 继续
				continue
			}
			for k := '1'; k <= '9'; k++ { //需要判断这行 这列 这小块有没有这个数  有的话++
				if isvalid(i, j, byte(k), board) { //都没有重复
					board[i][j] = byte(k) //把K 填入
					if solve(board) {     //找到则返回
						return true
					} else {
						board[i][j] = '.' //没找到回溯
					}
				}
			}
			return false
		}
	}
	return true
}
func solveSudoku(board [][]byte) {
	solve(board)
}
执行用时:4 ms, 在所有 Go 提交中击败了50.56%的用户
内存消耗:2 MB, 在所有 Go 提交中击败了95.10%的用户

缺失的第一个正数

给你一个未排序的整数数组 nums ,请你找出其中没有出现的最小的正整数。

请你实现时间复杂度为 O(n) 并且只使用常数级别额外空间的解决方案。

示例 1:
输入:nums = [1,2,0]
输出:3
func firstMissingPositive(nums []int) int {
	n := len(nums)
	for i := 0; i < n; i++ {
		for nums[i] > 0 && nums[i] < n && nums[nums[i]-1] != nums[i] {
			nums[i], nums[nums[i]-1] = nums[nums[i]-1], nums[i]
		}//置换, 注意这里不是if  for加了限制条件 可以把某位置的数直接放到原位置,如果是if的话 只换一次 换回来的数不一定在原位置
	}
	for i := 0; i < n; i++ {
		if nums[i] != i+1 {
			return i + 1
		}
	}
	return n + 1
}
func firstMissingPositive(nums []int) int {  //这他妈好狗
    n := len(nums)
    for i := 0; i < n; i++ {//将所有负数变为n+1
        if nums[i] <= 0 {
            nums[i] = n + 1
        }
    }
    for i := 0; i < n; i++ {//将对应位置变为负数
        num := abs(nums[i])
        if num <= n {
            fmt.Println(num-1)
            nums[num - 1] = -abs(nums[num - 1])
        }
    }
    for i := 0; i < n; i++ { //找正数下标加一  没变负数 证明这个没出现过
        if nums[i] > 0 {
            return i + 1
        }
    }
    return n + 1
}
func abs(x int) int {
    if x < 0 {
        return -x
    }
    return x
}

接雨水

给定 n 个非负整数表示每个宽度为 1 的柱子的高度图,计算按此排列的柱子,下雨之后能接多少雨水。

输入:height = [0,1,0,2,1,0,1,3,2,1,2,1]
输出:6
解释:上面是由数组 [0,1,0,2,1,0,1,3,2,1,2,1] 表示的高度图,在这种情况下,可以接 6 个单位的雨水(蓝色部分表示雨水)。 
示例 2:
输入:height = [4,2,0,3,2,5]
输出:9
func trap(height []int) int {
	c := 0
	p := 1
	a := 0
	b := len(height) - 1
	for i := 0; a < b; { //从头往后遍历
		for height[i] < p { //一个一个往上增  找到定位
			i++
			a++
			if i == b {  //越界就返回
				break
			}
		}
		for height[b] < p {  //找定位
			b--
			if b == 0 {
				break
			}
		}
		for j := a; j < b; j++ {//遍历定位中的值
			if height[j] < p {
				c++
			}
		}
		p++   //p++
	}
	return c
}
执行用时:1444 ms, 在所有 Go 提交中击败了5.43%的用户
内存消耗:4.4 MB, 在所有 Go 提交中击败了13.87%的用户

通配符匹配

给定一个字符串 (s) 和一个字符模式 § ,实现一个支持 ‘?’ 和 ‘*’ 的通配符匹配。

'?' 可以匹配任何单个字符。
'*' 可以匹配任意字符串(包括空字符串)。

两个字符串完全匹配才算匹配成功。

说明:
s 可能为空,且只包含从 a-z 的小写字母。
p 可能为空,且只包含从 a-z 的小写字母,以及字符 ? 和 *。

示例 1:

输入:
s = "aa"
p = "a"
输出: false
解释: "a" 无法匹配 "aa" 整个字符串。
func isMatch(s string, p string) bool {
	if len(p) == 0 { //len(p)=0 len(s)=0 true         len(p)=0 len(s)!=0  false
		if len(s) == 0 {
			return true
		}
		return false
	}
	if len(s) == 0 { //len(s)=0  len(p)!=0时  排除*
		for i := 0; i < len(p); {
			if p[i] == '*' {
				i++
			} else {
				return false
			}
		}
		return true
	}
	ss, pp := s[0], p[0]
	if ss == pp || pp == '?' {
		return isMatch(s[1:], p[1:])
	} else {
		if pp == '*' {
			if isMatch(s, p[1:]) == true {
				return true
			} else {
				if isMatch(s[1:], p) == true {
					return true
				} else {
					return false
				}
			}
		} else {
			return false
		}
	}
	return true
}
用递归做的 自认为没问题 但是超时了  很烦
func isMatch(s string, p string) bool {
	m, n := len(s), len(p)
	pp := make([][]bool, m+1) // 制作一个二维bool数组 表示字符串s的前i个字符和p中的前j个字符是否能匹配
	for i := 0; i <= m; i++ {
		pp[i] = make([]bool, n+1) //?防止数组越界  默认都为false
	}
	pp[0][0] = true //两个空字符串匹配
	for i:=1;i<=n;i++{
		if p[i-1]=='*'{
			pp[0][i]=true  //*匹配所有字符
		}else {
			break //跳出for循环 从第一个开始都为* 则为true 一直到不一样
		}
	}
	for i:=1;i<=m;i++{  //s选一 p从一选到最后 看是否匹配
		for j:=1;j<=n;j++{
			if p[j-1]=='*'{  //p为*号;
				pp[i][j]=pp[i][j-1]||pp[i-1][j]
			}else if p[j-1]=='?'|| s[i-1]==p[j-1]{ //p为? 或者这两个相等,看它前面的匹配 他就匹配
				pp[i][j]=pp[i-1][j-1]
			}
		}
	}
	return pp[m][n]
}
执行用时:20 ms, 在所有 Go 提交中击败了26.35%的用户
内存消耗:6.3 MB, 在所有 Go 提交中击败了63.81%的用户

N皇后

n 皇后问题 研究的是如何将 n 个皇后放置在 n×n 的棋盘上,并且使皇后彼此之间不能相互攻击。

给你一个整数 n ,返回所有不同的 n 皇后问题 的解决方案。

每一种解法包含一个不同的 n 皇后问题 的棋子放置方案,该方案中 ‘Q’ 和 ‘.’ 分别代表了皇后和空位。

输入:n = 4
输出:[[".Q..","...Q","Q...","..Q."],["..Q.","Q...","...Q",".Q.."]]
解释:如上图所示,4 皇后问题存在两个不同的解法。

N皇后2

n 皇后问题 研究的是如何将 n 个皇后放置在 n × n 的棋盘上,并且使皇后彼此之间不能相互攻击。

给你一个整数 n ,返回 n 皇后问题 不同的解决方案的数量。

输入:n = 4
输出:2
解释:如上图所示,4 皇后问题存在两个不同的解法。

排序序列

给出集合 [1,2,3,…,n],其所有元素共有 n! 种排列。

按大小顺序列出所有排列情况,并一一标记,当 n = 3 时, 所有排列如下:

"123"
"132"
"213"
"231"
"312"
"321"

给定 n 和 k,返回第 k 个排列。

示例 1:
输入:n = 3, k = 3
输出:"213"
示例 2:
输入:n = 4, k = 9
输出:"2314"

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值