Leetcode11-20

Leetcode11-20

11

题目:给定一个长度为 n 的整数数组 height 。有 n 条垂线,第 i 条线的两个端点是 (i, 0) 和 (i, height[i]) 。找出其中的两条线,使得它们与 x 轴共同构成的容器可以容纳最多的水。
返回容器可以储存的最大水量。
说明:你不能倾斜容器。

  1. 暴力枚举 O(n^2) 超出时间限制
func maxArea(height []int) int {
	ans := 0
	for i := 0; i < len(height); i++ {
		for j := i + 1; j < len(height); j++ {
			temp := (j - i) * min(height[i], height[j])
			ans = max(temp, ans)
		}
	}
	return ans
}

func min(x, y int) int {
	if x < y {
		return x
	}
	return y
}
func max(x, y int) int {
	if x > y {
		return x
	}
	return y
}

  1. 消状态 O(n)
func maxArea(height []int) int {
	ans := 0
	i, j := 0, len(height)-1
	for i < j {
		ans = max(ans, min(height[i], height[j])*(j-i))
		fmt.Println(ans, i, j)
		if height[i] < height[j] {
			i++
		} else {
			j--
		}
	}
	return ans
}

func min(x, y int) int {
	if x < y {
		return x
	}
	return y
}
func max(x, y int) int {
	if x > y {
		return x
	}
	return y
}
//执行用时:276 ms, 在所有 Go 提交中击败了5.19%的用户
//内存消耗:8.2 MB, 在所有 Go 提交中击败了91.76%的用户

12

题目:
请添加图片描述

  1. 模拟
var rl = []struct {
	num    int
	symbol string
}{
	{1000, "M"},
	{900, "CM"},
	{500, "D"},
	{400, "CD"},
	{100, "C"},
	{90, "XC"},
	{50, "L"},
	{40, "XL"},
	{10, "X"},
	{9, "IX"},
	{5, "V"},
	{4, "IV"},
	{1, "I"},
}

func intToRoman(num int) string {
	ans := ""
	for _, v := range rl {
		for num >= v.num {
			ans += v.symbol
			num -= v.num
		}
	}
	return ans
}
//执行用时:4 ms, 在所有 Go 提交中击败了90.14%的用户
//内存消耗:3.1 MB, 在所有 Go 提交中击败了48.49%的用户

13

题目:请添加图片描述

  1. 先检索前两个字符是否在哈希表中,否则看一个字符
func romanToInt(s string) int {
	ans := 0
	src := map[string]int{
		"M":  1000,
		"CM": 900,
		"D":  500,
		"CD": 400,
		"C":  100,
		"XC": 90,
		"L":  50,
		"XL": 40,
		"X":  10,
		"IX": 9,
		"V":  5,
		"IV": 4,
		"I":  1,
	}
	i := 0
	for i < len(s) {
		if i+1 < len(s) {
			if v, ok := src[s[i:i+2]]; ok {
				fmt.Println(1, s[i:i+2])

				ans += v
				i += 2
			} else {
				ans += src[s[i:i+1]]
				fmt.Println(2, s[i:i+1])

				i++
			}
		} else {
			ans += src[s[i:i+1]]
			i++
		}
	}
	return ans
}
//执行用时:4 ms, 在所有 Go 提交中击败了87.80%的用户
//内存消耗:5.1 MB, 在所有 Go 提交中击败了5.27%的用户
  1. 前一个字符比后一个字符小则减去这个对应值,否则加上
func romanToInt(s string) int {
	ans := 0
	src := map[byte]int{'I': 1, 'V': 5, 'X': 10, 'L': 50, 'C': 100, 'D': 500, 'M': 1000}
	for i := range s {
		value := src[s[i]]
		if i < len(s)-1 && value < src[s[i+1]] {
			ans -= value
		} else {
			ans += value
		}
	}
	return ans
}
//执行用时:4 ms, 在所有 Go 提交中击败了87.80%的用户
//内存消耗:2.7 MB, 在所有 Go 提交中击败了100.00%的用户

14

题目:编写一个函数来查找字符串数组中的最长公共前缀。
如果不存在公共前缀,返回空字符串 “”。

  1. 横向比较
func longestCommonPrefix(strs []string) string {
	if len(strs) == 0 {
		return ""
	}
	if len(strs) == 1 {
		return strs[0]
	}
	prefix := strs[0]
	for i := 1; i < len(strs); i++ {
		prefix = lcp(prefix, strs[i])
		if len(prefix) == 0 {
			return ""
		}
	}
	return prefix
}
func lcp(str1, str2 string) string {
	length := min(len(str1), len(str2))
	i := 0
	for i < length && str1[i] == str2[i] {
		i++
	}
	return str1[:i]
}
func min(x, y int) int {
	if x < y {
		return x
	}
	return y
}
//执行用时:0 ms, 在所有 Go 提交中击败了100.00%的用户
//内存消耗:2.2 MB, 在所有 Go 提交中击败了60.90%的用户
  1. 纵向比较
func longestCommonPrefix(strs []string) string {
	if len(strs) == 0 {
		return ""
	}
	if len(strs) == 1 {
		return strs[0]
	}
	for i := 0; i < len(strs[0]); i++ {
		for j := 1; j < len(strs); j++ {
			if i == len(strs[j]) || strs[0][i] != strs[j][i] {
				return strs[0][:i]
			}
		}
	}
	return strs[0]
}
//执行用时:0 ms, 在所有 Go 提交中击败了100.00%的用户
//内存消耗:2.2 MB, 在所有 Go 提交中击败了90.85%的用户
  1. 分治法
func longestCommonPrefix(strs []string) string {
	if len(strs) == 0 {
		return ""
	}
	var lcp func(int, int) string
	lcp = func(start, end int) string {
		if start == end {
			return strs[start]
		}
		mid := (start + end) / 2
		lcpLeft, lcpRight := lcp(start, mid), lcp(mid+1, end)
		minlength := min(len(lcpLeft), len(lcpRight))
		for i := 0; i < minlength; i++ {
			if lcpLeft[i] != lcpRight[i] {
				return lcpLeft[:i]
			}
		}
		return lcpLeft[:minlength]
	}
	return lcp(0, len(strs)-1)
}
func min(x, y int) int {
	if x < y {
		return x
	}
	return y
}
//执行用时:0 ms, 在所有 Go 提交中击败了100.00%的用户
//内存消耗:2.2 MB, 在所有 Go 提交中击败了90.98%的用户

15

题目:给你一个整数数组 nums ,判断是否存在三元组 [nums[i], nums[j], nums[k]] 满足 i != j、i != k 且 j != k ,同时还满足 nums[i] + nums[j] + nums[k] == 0 。请
你返回所有和为 0 且不重复的三元组。
注意:答案中不可以包含重复的三元组。

  1. 排序+三重循环==>二重循环
func threeSum(nums []int) [][]int {
	ans := [][]int{}
	sort.Slice(nums, func(i, j int) bool { return nums[i] < nums[j] })
	// fmt.Println(nums)
	for i := 0; i < len(nums); i++ {
		if i > 0 && nums[i] == nums[i-1] {
			continue
		}
		third := len(nums) - 1
		target := -1 * nums[i]
		for j := i + 1; j < len(nums); j++ {
			if j > i+1 && nums[j] == nums[j-1] {
				continue
			}
			for j < third && nums[j]+nums[third] > target {
				third--
			}
			if j == third {
				break
			}
			if nums[j]+nums[third] == target {
				ans = append(ans, []int{nums[i], nums[j], nums[third]})
			}
		}
	}
	return ans
}
//执行用时:40 ms, 在所有 Go 提交中击败了43.53%的用户
//内存消耗:8.3 MB, 在所有 Go 提交中击败了8.48%的用户

16

题目:给你一个长度为 n 的整数数组 nums 和 一个目标值 target。请你从 nums 中选出三个整数,使它们的和与 target 最接近。
返回这三个数的和。
假定每组输入只存在恰好一个解。

  1. 暴力三次循环
func threeSumClosest(nums []int, target int) int {
	ans := math.MaxInt64
	ans1 := 0
	for i := 0; i < len(nums); i++ {
		if i > 0 && nums[i] == nums[i-1] {
			continue
		}
		for j := i + 1; j < len(nums); j++ {
			if j > i+1 && nums[j] == nums[j-1] {
				continue
			}
			for m := j + 1; m < len(nums); m++ {
				if ans > abs(target-nums[i]-nums[j]-nums[m]) {
					ans = min(ans, abs(target-nums[i]-nums[j]-nums[m]))
					ans1 = nums[i] + nums[j] + nums[m]
				}

			}
		}
	}
	return ans1
}
func min(x, y int) int {
	if x < y {
		return x
	}
	return y
}
func abs(x int) int {
	if x < 0 {
		return -x
	}
	return x
}
//执行用时:772 ms, 在所有 Go 提交中击败了5.09%的用户
//内存消耗:3 MB, 在所有 Go 提交中击败了28.20%的用户
  1. 排序+双指针
func threeSumClosest(nums []int, target int) int {
	sort.Ints(nums)
	ans := math.MaxInt32
	update := func(cur int) {
		if abs(cur-target) < abs(ans-target) {
			ans = cur
		}
	}
	for i := 0; i < len(nums); i++ {
		if i > 0 && nums[i] == nums[i-1] {
			continue
		}
		j, k := i+1, len(nums)-1
		for j < k {
			sum := nums[i] + nums[j] + nums[k]
			if sum == target {
				return sum
			}
			update(sum)
			if sum > target {
				k0 := k - 1
				for k0 > j && nums[k0] == nums[k] {
					k0--
				}
				k = k0
			} else {
				j0 := j + 1
				for j0 < k && nums[j0] == nums[j] {
					j0++
				}
				j = j0
			}
		}
	}
	return ans
}
func abs(x int) int {
	if x < 0 {
		return -x
	}
	return x
}
//执行用时:16 ms, 在所有 Go 提交中击败了47.91%的用户
//内存消耗:3 MB, 在所有 Go 提交中击败了69.45%的用户

17

题目:给定一个仅包含数字 2-9 的字符串,返回所有它能表示的字母组合。答案可以按 任意顺序 返回。给出数字到字母的映射如下(与电话按键相同)。注意 1 不对应任何字母。

  1. 获取第一个数字更新string表,获取下一个数字和string表结合再更新string表,以此类推
func letterCombinations(digits string) []string {
	ans := []string{}
	src := map[byte]string{
		'2': "abc",
		'3': "def",
		'4': "ghi",
		'5': "jkl",
		'6': "mno",
		'7': "pqrs",
		'8': "tuv",
		'9': "wxyz",
	}
	n := len(digits)
	for i := 0; i < n; i++ {
		temp := []string{}
		if i == 0 {
			symbolset := src[digits[i]]
			for j := 0; j < len(symbolset); j++ {
				temp = append(temp, string(symbolset[j]))
			}
			// fmt.Println(temp)
		} else {
			symbolset := src[digits[i]]
			for _, v := range ans {
				for k := 0; k < len(symbolset); k++ {
					temp = append(temp, v+string(symbolset[k]))
				}
			}
		}
		ans = temp
	}
	return ans
}
//执行用时:0 ms, 在所有 Go 提交中击败了100.00%的用户
//内存消耗:1.9 MB, 在所有 Go 提交中击败了60.02%的用户

  1. 回溯
var combinations []string
var src map[string]string = map[string]string{
	"2": "abc",
	"3": "def",
	"4": "ghi",
	"5": "jkl",
	"6": "mno",
	"7": "pqrs",
	"8": "tuv",
	"9": "wxyz",
}

func letterCombinations(digits string) []string {
	if len(digits) == 0 {
		return []string{}
	}
	combinations = []string{}
	backtrack(digits, 0, "")
	return combinations
}
func backtrack(digits string, index int, combination string) {
	if index == len(digits) {
		combinations = append(combinations, combination)
	} else {
		digit := string(digits[index])
		letters := src[digit]
		lettersCount := len(letters)
		for i := 0; i < lettersCount; i++ {
			backtrack(digits, index+1, combination+string(letters[i]))
		}
	}
}
//执行用时:0 ms, 在所有 Go 提交中击败了100.00%的用户
//内存消耗:1.9 MB, 在所有 Go 提交中击败了50.75%的用户

18

题目:给你一个由 n 个整数组成的数组 nums ,和一个目标值 target 。请你找出并返回满足下述全部条件且不重复的四元组 [nums[a], nums[b], nums[c], nums[d]] (若两个四元组元素一一对应,则认为两个四元组重复):
0 <= a, b, c, d < n
a、b、c 和 d 互不相同
nums[a] + nums[b] + nums[c] + nums[d] == target
你可以按 任意顺序 返回答案 。

  1. 排序+三重循环
func fourSum(nums []int, target int) [][]int {
	ans := [][]int{}
	sort.Ints(nums)
	for i := 0; i < len(nums); i++ {
		if i > 0 && nums[i] == nums[i-1] {
			continue
		}
		for j := i + 1; j < len(nums); j++ {
			if j > i+1 && nums[j] == nums[j-1] {
				continue
			}
			// temp := target - nums[i] - nums[j]
			m, n := j+1, len(nums)-1
			for m < n {
				sum := nums[i] + nums[j] + nums[m] + nums[n]
				if sum == target {
					ans = append(ans, []int{nums[i], nums[j], nums[m], nums[n]})
					m0 := m + 1
					for m0 < n && nums[m0] == nums[m] {
						m0++
					}
					m = m0
					n0 := n - 1
					for n0 > m && nums[n0] == nums[n] {
						n0--
					}
					n = n0
				} else if sum > target {
					n0 := n - 1
					for n0 > m && nums[n0] == nums[n] {
						n0--
					}
					n = n0
				} else {
					m0 := m + 1
					for m0 < n && nums[m0] == nums[m] {
						m0++
					}
					m = m0
				}
			}
		}
	}
	return ans
}
//执行用时:20 ms, 在所有 Go 提交中击败了14.97%的用户
//内存消耗:2.7 MB, 在所有 Go 提交中击败了19.44%的用户

19

题目:给你一个链表,删除链表的倒数第 n 个结点,并且返回链表的头结点。

  1. 计算链表长度
func removeNthFromEnd(head *ListNode, n int) *ListNode {
	temp1 := head
	temp2 := head

	length := 0
	for temp1 != nil {
		length++
		temp1 = temp1.Next
	}
	length1 := length - n
    if length==1&&length1==0{
        return nil
    }else if length1 ==0{
        return head.Next
    }
	for length1 > 1 {
        length1--
		temp2 = temp2.Next
	}
	temp2.Next = temp2.Next.Next
	return head
}
//执行用时:0 ms, 在所有 Go 提交中击败了100.00%的用户
//内存消耗:2.1 MB, 在所有 Go 提交中击败了99.93%的用户
  1. 计算链表长度优化
func getListLength(head *ListNode) (length int) {
	for ; head != nil; head = head.Next {
		length++
	}
	return
}
func removeNthFromEnd(head *ListNode, n int) *ListNode {
	length := getListLength(head)
	dummp := &ListNode{0, head}
	cur := dummp
	for i := 0; i < length-n; i++ {
		cur = cur.Next
	}
	cur.Next = cur.Next.Next
	return dummp.Next
}
//执行用时:0 ms, 在所有 Go 提交中击败了100.00%的用户
//内存消耗:2.1 MB, 在所有 Go 提交中击败了99.93%的用户
func removeNthFromEnd(head *ListNode, n int) *ListNode {
	nodes := []*ListNode{}
	dummy := &ListNode{0, head}
	for node := dummy; node != nil; node = node.Next {
		nodes = append(nodes, node)
	}
	prev := nodes[len(nodes)-1-n]
	prev.Next = prev.Next.Next
	return dummy.Next
}
//执行用时:0 ms, 在所有 Go 提交中击败了100.00%的用户
//内存消耗:2.2 MB, 在所有 Go 提交中击败了5.53%的用户
  1. 双指针
func removeNthFromEnd(head *ListNode, n int) *ListNode {
	dummy := &ListNode{0, head}
	first, second := head, dummy
	for i := 0; i < n; i++ {
		first = first.Next
	}
	for first != nil {
		first = first.Next
		second = second.Next
	}
	second.Next = second.Next.Next
	return dummy.Next
}
//执行用时:0 ms, 在所有 Go 提交中击败了100.00%的用户
//内存消耗:2.1 MB, 在所有 Go 提交中击败了99.93的用户

20

题目:给定一个只包括 ‘(’,‘)’,‘{’,‘}’,‘[’,‘]’ 的字符串 s ,判断字符串是否有效。
有效字符串需满足:
左括号必须用相同类型的右括号闭合。
左括号必须以正确的顺序闭合。
每个右括号都有一个对应的相同类型的左括号。

  1. 匹配到对应括号就删除,看最终字符串是否为空
func isValid(s string) bool {
	src := map[byte]byte{
		')': '(',
		']': '[',
		'}': '{',
	}
	ans := ""
	for i := 0; i < len(s); i++ {
		if i == 0 {
			ans += string(s[i])
			continue
		}
		temp, ok := src[s[i]]
		if ok && len(ans) > 0 && ans[len(ans)-1] == temp {
			ans = ans[:len(ans)-1]
		} else {
			ans += string(s[i])
		}
		// fmt.Println(string(s[i]))
		// fmt.Println(ans, 2)
	}
	return len(ans) == 0
}
//执行用时:0 ms, 在所有 Go 提交中击败了100.00%的用户
//内存消耗:6.4 MB, 在所有 Go 提交中击败了5.03%的用户
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值