leetcode刷题01-10

leetcode01-10

01

题目:给定一个整数数组 nums 和一个整数目标值 target,请你在该数组中找出 和为目标值 target 的那 两个
整数,并返回它们的数组下标。 你可以假设每种输入只会对应一个答案。但是,数组中同一个元素在答案里不能重复出现。 你可以按任意顺序返回答案。

  1. 第一种方法暴力枚举
func twoSum(nums []int, target int) []int {
    for i,v:=range nums{
        for j,m:=range nums[:i]{
            if v+m == target{
                return []int{i,j}
            }
        }
    }
    return []int{0,0}
}
//执行用时:32 ms, 在所有 Go 提交中击败了15.17%的用户
//内存消耗:3.4 MB, 在所有 Go 提交中击败了99.10%的用户
  1. 哈希表
func twoSum(nums []int, target int) []int {
    src:=map[int]int{}
    for i,v:=range nums{
        if value,ok:=src[target-v];ok{
            return []int{i,value}
        }else{
            src[v] = i
        }
    }
    return []int{0,0}
}
// 执行用时:4 ms, 在所有 Go 提交中击败了94.84%的用户
// 内存消耗:4.1 MB, 在所有 Go 提交中击败了61.35%的用户

02

题目:给你两个 非空 的链表,表示两个非负的整数。它们每位数字都是按照 逆序 的方式存储的,并且每个节点只能存储 一位 数字。
请你将两个数相加,并以相同形式返回一个表示和的链表。
你可以假设除了数字 0 之外,这两个数都不会以 0 开头。

  1. 模拟相加过程,注意进位
func addTwoNumbers(l1 *ListNode, l2 *ListNode) (head *ListNode) {
	var res *ListNode
	temp := 0
	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 + temp
		sum, temp = sum%10, sum/10
		if head == nil {
			head = &ListNode{Val: sum}
			res = head
		} else {
			res.Next = &ListNode{Val: sum}
			res = res.Next
		}
	}
	if temp > 0 {
		res.Next = &ListNode{Val: temp}
	}
	return 
}
//执行用时:8 ms, 在所有 Go 提交中击败了80.69%的用户
//内存消耗:4.4 MB, 在所有 Go 提交中击败了92.84%的用户

03

题目:给定一个字符串 s ,请你找出其中不含有重复字符的 最长子串 的长度。

  1. 暴力,特殊处理大于2的字符串,遍历字符串的各个切片,若有重复字符则保留最大值并break,若无重复则保留当前切片大小为最大值,速度过慢需优化
func lengthOfLongestSubstring(s string) int {
	if len(s) < 2 {
		return len(s)
	}
	res := 0
	for j := 0; j <= len(s); j++ {
	    flag := false
		src := map[rune]int{}
		for _, v := range s[j:] {
			if _, ok := src[v]; !ok {
				src[v]++
			} else {
				flag = true
				fmt.Println(src)
				res = max(res, len(src))
				break
			}
		}
        if !flag {
            res = max(res, len(src))
        }   
	}
	
	return res
}

func max(i, j int) int {
	if i < j {
		return j
	}
	return i
}

//执行用时:1340 ms, 在所有 Go 提交中击败了5.54%的用户
//内存消耗:7 MB, 在所有 Go 提交中击败了5.29%的用户
  1. 滑动窗口
func lengthOfLongestSubstring(s string) int {
    m:=map[byte]int{}
    rk,ans:=-1,0
    for i:=0;i<len(s);i++{
        if i!=0{
            delete(m,s[i-1])
        }
        for rk+1<len(s)&&m[s[rk+1]]==0{
            m[s[rk+1]]++
            rk++
        }
        ans = max(ans,len(m))
    }
    return ans
}
func max(x,y int)int{
    if x<y{
        return y
    }
    return x
}

//执行用时:16 ms, 在所有 Go 提交中击败了17.22%的用户
//内存消耗:2.6 MB, 在所有 Go 提交中击败了72.98%的用户

04

题目:给定两个大小分别为 m 和 n 的正序(从小到大)数组 nums1 和 nums2。请你找出并返回这两个正序数组的 中位数 。算法的时间复杂度应该为 O(log (m+n)) 。——困难题

  1. 合并数组
func findMedianSortedArrays(nums1 []int, nums2 []int) float64 { //O(MAX(m,n))
	m := len(nums1)
	n := len(nums2)
	nums := make([]int, m+n)
	m1, n1, i := 0, 0, 0
	for m1 < m || n1 < n {
		if m1 < m && n1 < n {
			if nums1[m1] < nums2[n1] {
				nums[i] = nums1[m1]
				m1++
			} else {
				nums[i] = nums2[n1]
				n1++
			}
		} else if n1 < n {
			nums[i] = nums2[n1]
			n1++
		} else if m1 < m {
			nums[i] = nums1[m1]
			m1++
		}
		i++
	}
	var res float64
	if (m+n)%2 == 0 {
		res = (float64(nums[(m+n)/2]) + float64(nums[(m+n)/2-1])) / 2
	} else {
		res = float64(nums[(m+n)/2])
	}
	return res
}

//执行用时:12 ms, 在所有 Go 提交中击败了73.24%的用户
//内存消耗:5.4 MB, 在所有 Go 提交中击败了33.61%的用户
  1. 直接找两个数组第K位的数
func findMedianSortedArrays(nums1 []int, nums2 []int) float64 {
	totallength := len(nums1) + len(nums2)
	if (totallength)%2 == 1 {
		midIndex := totallength/2 + 1
		return float64(getKthElement(nums1, nums2, midIndex))
	} else {
		midIndex1, midIndex2 := totallength/2, totallength/2+1
		return float64(getKthElement(nums1, nums2, midIndex1)+getKthElement(nums1, nums2, midIndex2)) / 2.0
	}
}
func getKthElement(nums1, nums2 []int, k int) int { //二分查找两个表中第k小的数
	index1, index2 := 0, 0
	for {
		if index1 == len(nums1) {
			return nums2[index2+k-1]
		}
		if index2 == len(nums2) {
			return nums1[index1+k-1]
		}
		if k == 1 {
			return min(nums1[index1], nums2[index2])
		}
		half := k / 2
		newIndex1 := min(index1+half, len(nums1)) - 1
		newIndex2 := min(index2+half, len(nums2)) - 1
		pivot1, pivot2 := nums1[newIndex1], nums2[newIndex2]
		if pivot1 <= pivot2 {
			k -= (newIndex1 - index1 + 1)
			index1 = newIndex1 + 1
		} else {
			k -= (newIndex2 - index2 + 1)
			index2 = newIndex2 + 1
		}
	}
}
func min(x, y int) int {
	if x < y {
		return x
	}
	return y
}
//执行用时:20 ms, 在所有 Go 提交中击败了14.00%的用户
//内存消耗:4.9 MB, 在所有 Go 提交中击败了53.03%的用户

05

题目:给你一个字符串 s,找到 s 中最长的回文子串。如果字符串的反序与原始字符串相同,则该字符串称为回文字符串。

  1. 动态规划

func longestPalindrome(s string) string {
	length := len(s)
	if length <= 1 {
		return s
	}
	dp := make([][]bool, length)
	start := 0
	maxlen := 1
	for r := 0; r < length; r++ {
		dp[r] = make([]bool, length)
		dp[r][r] = true
		for l := 0; l < r; l++ {
			if s[l] == s[r] && (r-1 < l+1 || dp[l+1][r-1]) {
				dp[l][r] = true
			} else {
				dp[l][r] = false
			}
			if dp[l][r] {
				curlen := r - l + 1
				if curlen > maxlen {
					maxlen = curlen
					start = l
				}
			}
		}
	}
	return s[start : start+maxlen]
}
//执行用时:96 ms, 在所有 Go 提交中击败了13.25%的用户
//内存消耗:6.7 MB, 在所有 Go 提交中击败了16.68%的用户
  1. 中心扩散
func longestPalindrome(s string) string {
	if s == "" {
		return ""
	}
	start, end := 0, 0
	for i := 0; i < len(s); i++ {
		start1, end1 := expandAroundCenter(s, i, i)
		start2, end2 := expandAroundCenter(s, i, i+1)
		if end1-start1 > end-start {
			start, end = start1, end1
		}
		if end2-start2 > end-start {
			start, end = start2, end2
		}
	}
	return s[start : end+1]
}
func expandAroundCenter(s string, left, right int) (int, int) {
	for ; left >= 0 && right < len(s) && s[left] == s[right]; left, right = left-1, right+1 {
	}
	return left + 1, right - 1
}
//执行用时:4 ms, 在所有 Go 提交中击败了92.03%的用户
//内存消耗:2.3 MB, 在所有 Go 提交中击败了82.58%的用户

06

题目:将一个给定字符串 s 根据给定的行数 numRows ,以从上往下、从左到右进行 Z 字形排列。
比如输入字符串为 “PAYPALISHIRING” 行数为 3 时,排列如下:
在这里插入图片描述
之后,你的输出需要从左往右逐行读取,产生出一个新的字符串,比如:“PAHNAPLSIIGYIR”。
请你实现这个将字符串进行指定行数变换的函数:
string convert(string s, int numRows);

  1. 暴力
func convert(s string, numRows int) string {
	if numRows <= 1 {
		return s
	}
	strs := make([]string, numRows)
	// fmt.Println(strs[1] + "123")
	i := 0
	j := 0
	flag := false
	for i < len(s) {
		if j == -1 {
			flag = false
			j = 1
		} else if j == numRows {
			flag = true
			j = numRows - 2
		}
		strs[j] += string(s[i])
		if flag {
			j--
		} else {
			j++
		}

		i++
	}
	// fmt.Println(strs)
	res := ""
	for _, v := range strs {
		res += v
	}
	return res
}
//执行用时:8 ms, 在所有 Go 提交中击败了70.88%的用户
//内存消耗:6.9 MB, 在所有 Go 提交中击败了30.88%的用户

07

题目:给你一个 32 位的有符号整数 x ,返回将 x 中的数字部分反转后的结果。
如果反转后整数超过 32 位的有符号整数的范围 [−231,231 − 1] ,就返回 0。
假设环境不允许存储 64 位整数(有符号或无符号)。

  1. 暴力
func reverse(x int) int {
	flag := false
	if x < 0 {
		x = -x
	} else {
		flag = true
	}
	res := 0
	for x > 0 {
		temp := x % 10
		res = res*10 + temp
		x /= 10
	}
	if res >= int(math.Pow(2, 31)) {
		return 0
	}
	if flag {
		return res
	}
	return -res
}
//执行用时:0 ms, 在所有 Go 提交中击败了100.00%的用户
//内存消耗:2 MB, 在所有 Go 提交中击败了14.86%的用户

08

题目:
在这里插入图片描述

  1. 模拟
func myAtoi(s string) int {
	s = strings.TrimSpace(s)
	i := 0
	res := 0
	flag := true
	for i < len(s) {
		if i == 0 {
			if s[i] == '-' {
				flag = false
				i++
				continue
			} else if s[i] == '+' {
				i++
				continue
			}
		}
		if s[i] >= '0' && s[i] <= '9' {
			res = res*10 + int(s[i]-'0')
			if flag && res > 2147483647 {
				return 2147483647
			} else if !flag && res > 2147483648 {
				return -2147483648
			}
		} else {
			break
		}
		i++
	}
	fmt.Println(res)
	if flag {
		return res
	}
	return -res
}
//执行用时:0 ms, 在所有 Go 提交中击败了100.00%的用户
//内存消耗:2.1 MB, 在所有 Go 提交中击败了37.43%的用户
  1. 状态机
func myAtoi(s string) int {
	const (
		START = iota
		SIGNED
		IN_NUMBER
		END
	)
	table := map[int][4]int{
		START:     [4]int{START, SIGNED, IN_NUMBER, END},
		SIGNED:    [4]int{END, END, IN_NUMBER, END},
		IN_NUMBER: [4]int{END, END, IN_NUMBER, END},
		END:       [4]int{END, END, END, END},
	}
	getCol := func(c byte) int {
		if c == ' ' {
			return 0
		}
		if c == '+' || c == '-' {
			return 1
		}
		if c >= '0' && c <= '9' {
			return 2
		}
		return 3
	}
	state := START
	sign := 1
	ans := 0
	for i := range s {
		state = table[state][getCol(s[i])]
		if state == IN_NUMBER {
			ans = ans*10 + int(s[i]-'0')
			if ans*sign > math.MaxInt32 {
				return math.MaxInt32
			}
			if ans*sign < math.MinInt32 {
				return math.MinInt32
			}
		} else if state == SIGNED {
			if s[i] == '-' {
				sign = -1
			}
		}
	}
	return ans * sign
}
//执行用时:0 ms, 在所有 Go 提交中击败了100.00%的用户
//内存消耗:2.1 MB, 在所有 Go 提交中击败了21.28%的用户

09

题目:给你一个整数 x ,如果 x 是一个回文整数,返回 true ;否则,返回 false 。
回文数是指正序(从左向右)和倒序(从右向左)读都是一样的整数。
例如,121 是回文,而 123 不是。

  1. 暴力
func isPalindrome(x int) bool {
	if x < 0 {
		return false
	}
	s := strconv.Itoa(x)
	if len(s) == 1 {
		return true
	}
	i, j := 0, len(s)-1
	for i < j {
		if s[i] != s[j] {
			return false
		}
		i++
		j--
	}
	return true
}

//执行用时:24 ms, 在所有 Go 提交中击败了14.56%的用户
//内存消耗:4.6 MB, 在所有 Go 提交中击败了35.59%的用户
  1. 翻转数字判断是否相同
func isPalindrome(x int) bool {
	m := x
	temp := 0
	for x > 0 {
		temp = temp*10 + x%10
		x /= 10
	}
	fmt.Println(temp)
	return temp == m
}
//执行用时:20 ms, 在所有 Go 提交中击败了28.86%的用户
//内存消耗:4.5 MB, 在所有 Go 提交中击败了42.43%的用户

10

题目:给你一个字符串 s 和一个字符规律 p,请你来实现一个支持 ‘.’ 和 ‘’ 的正则表达式匹配。
‘.’ 匹配任意单个字符
'
’ 匹配零个或多个前面的那一个元素
所谓匹配,是要涵盖 整个 字符串 s的,而不是部分字符串。——困难题

  1. 动态规划
func isMatch(s string, p string) bool {
	m, n := len(s), len(p)
	matchs := func(i, j int) bool {
		if i == 0 {
			return false
		}
		if p[j-1] == '.' {
			return true
		}
		return s[i-1] == p[j-1]
	}
	//初始化动态规划数组
	f := make([][]bool, m+1)
	for i := 0; i < len(f); i++ {
		f[i] = make([]bool, n+1)
	}
	f[0][0] = true

	for i := 0; i <= m; i++ {
		for j := 1; j <= n; j++ {
			if p[j-1] == '*' {
				f[i][j] = f[i][j] || f[i][j-2]
				if matchs(i, j-1) {
					f[i][j] = f[i][j] || f[i-1][j]
				}
			} else if matchs(i, j) {
				f[i][j] = f[i][j] || f[i-1][j-1]
			}
		}
	}
	return f[m][n]
}
//执行用时:0 ms, 在所有 Go 提交中击败了100.00%的用户
//内存消耗:2.2 MB, 在所有 Go 提交中击败了28.21%的用户
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值