算法--week2

一、简单:

            1.有效的括号
            给定一个只包括 '(',')','{','}','[',']' 的字符串 s ,判断字符串是否有效。

有效字符串需满足:
左括号必须用相同类型的右括号闭合。
左括号必须以正确的顺序闭合。
**解题思路:**判断括号的有效性可以使用「栈」这一数据结构来解决。

我们遍历给定的字符串 ss。当我们遇到一个左括号时,我们会期望在后续的遍历中,有一个相同类型的右括号将其闭合。由于后遇到的左括号要先闭合,因此我们可以将这个左括号放入栈顶。

当我们遇到一个右括号时,我们需要将一个相同类型的左括号闭合。此时,我们可以取出栈顶的左括号并判断它们是否是相同类型的括号。如果不是相同的类型,或者栈中并没有左括号,那么字符串 ss 无效,返回 \text{False}False。为了快速判断括号的类型,我们可以使用哈希表存储每一种括号。哈希表的键为右括号,值为相同类型的左括号。

在遍历结束后,如果栈中没有左括号,说明我们将字符串 ss 中的所有左括号闭合,返回 \text{True}True,否则返回 \text{False}False。

注意到有效字符串的长度一定为偶数,因此如果字符串的长度为奇数,我们可以直接返回 \text{False}False,省去后续的遍历判断过程。
我这里用的是切片代替栈,思路是一样的。

func main() {
fmt.Println(isValid("{{[]}}"))
}

func isValid(s string) bool {
	flag := false
	m := make(map[byte]byte)
	m['('] = ')'
	m['['] = ']'
	m['{'] = '}'
	sli := make([]byte, 0)
	if len(s) == 0 {
		return true
	}
	if len(s)%2 == 1 {
		return false
	}
	for i, b := range s {
		if i == 0 && (s[i] == ')' || s[i] == ']' || s[i] == '}') {
			return false
		}//如果字符串第一个字符就是右括号,则返回false
		if b == '(' || b == '[' || b == '{' {
			sli = append(sli, byte(b))//如果字符串里有左括号,则把左括号放到切片中
		} else if b == ')' || b == ']' || b == '}' {
			//如果字符串中有右括号了
			left := sli[len(sli)-1]//从切片中取出栈顶的左括号
			sli = sli[:len(sli)-1]//更新切片
			if m[left] == byte(b) {
				flag = true//判断左右括号是否匹配
			} else {
				return false
			}
		}
	return flag
}

运行截图:
在这里插入图片描述
提交截图:
在这里插入图片描述
出现的问题:在提交的时候报了空指针异常。但是在运行过程中并没有出现问题,所以,我就按照官方发给的代码交了上去。
2.删除有序数组中的重复项
给你一个 升序排列 的数组 nums ,请你 原地 删除重复出现的元素,使每个元素 只出现一次 ,返回删除后数组的新长度。元素的 相对顺序 应该保持 一致 。

由于在某些语言中不能改变数组的长度,所以必须将结果放在数组nums的第一部分。更规范地说,如果在删除重复项之后有 k 个元素,那么 nums 的前 k 个元素应该保存最终结果。

将最终结果插入 nums 的前 k 个位置后返回 k 。

不要使用额外的空间,你必须在 原地 修改输入数组 并在使用 O(1) 额外空间的条件下完成。

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/remove-duplicates-from-sorted-array
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
思路:
在这里插入图片描述

代码:

n := len(nums)
	if n<2{
		return n//如果数组中没有元素或只有一个元素,则不存在重复元素
	}
	low := 0
	fast := 0
	for fast<n {
		if nums[low]==nums[fast]{
			fast++//快指针先走
		}else{
			low++
			nums[low] = nums[fast]//如果后一个元素和前一个元素不相等,那么就把快指针的元素放入慢指针中
			fast++
		}
	}
	nums = nums[:low+1]//更新数组
	return low+1

运行截图:
在这里插入图片描述

提交截图:
在这里插入图片描述
遇到的问题:开始没有想到数组元素为1个或0个的时候

if n<2{
		return n//如果数组中没有元素或只有一个元素,则不存在重复元素
	}

3.移除元素
给你一个数组 nums 和一个值 val,你需要 原地 移除所有数值等于 val 的元素,并返回移除后数组的新长度。

不要使用额外的数组空间,你必须仅使用 O(1) 额外空间并 原地 修改输入数组。

元素的顺序可以改变。你不需要考虑数组中超出新长度后面的元素。

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/remove-element
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
解法一:
双指针法:

func removeElement(nums []int, val int) int {
	n := 0
	for i := 0; i < len(nums); i ++ {
		if nums[i] != val {
			nums[n] = nums[i]
			n++
		}
	}
	return n
}

解法二:切片删除法

func removeElement1(nums []int, val int) int {
	for i := 0; i < len(nums); {
		if nums[i] == val {
			nums = append(nums[:i], nums[i + 1 :]...)//如果数组中出现了val,则把后一个元素赋值给val原先的位置。
		} else {
			i ++
		}
	}
	return len(nums)
}

运行截图:
在这里插入图片描述
提交截图:
在这里插入图片描述
中等:
1.三数之和:给你一个包含 n 个整数的数组 nums,判断 nums 中是否存在三个元素 a,b,c ,使得 a + b + c = 0 ?请你找出所有和为 0 且不重复的三元组。

注意:答案中不可以包含重复的三元组。

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/3sum
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

func threesum(nums []int)  [][]int{
	var res [][]int//最后要返回的结果数组
	if len(nums) <3{
		return res
	}
	sort.Ints(nums)//给nums排序
	for i:=0;i<len(nums);i++{
		if nums[i]>0 {
			return res
		}//因为已经排好序,所以,如果出现大于0的数,后面的a+b+c一定大于0,直接返回res
		if i>0 && nums[i]==nums[i-1] {
			continue
		}//删除重复元组
		l,r:=i+1,len(nums)-1
		for l<r {
			sum:=nums[i]+nums[l]+nums[r]
			if sum==0 {
				temp:=[]int{nums[l],nums[i],nums[r]}
				res=append(res,temp)
				for l<r && nums[l]==nums[l+1]{
					l++
				}
				for l<r && nums[r]==nums[r-1] {
					r--
				}
				
				l++//判断左界和右界是否和下一位重复,去除重复解。同时,将 l , r l, rl,r移动到下一位置,寻找新的解。
				
				r--
			}else if sum>0 {
				r--
			} else if sum<0 {
				l++
			}
		}

	}
return res
}

结果截图:
在这里插入图片描述
提交截图:
在这里插入图片描述

2.盛水最多的容器
给定一个长度为 n 的整数数组 height 。有 n 条垂线,第 i 条线的两个端点是 (i, 0) 和 (i, height[i]) 。

找出其中的两条线,使得它们与 x 轴共同构成的容器可以容纳最多的水。

返回容器可以储存的最大水量。

说明:你不能倾斜容器。
在这里插入图片描述

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/container-with-most-water
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
思路:使用双指针的方法,从两边想中间移动,每次移动高度小的指针,每次计算找出最大值

代码:

func maxArea(height []int) int {

	max := 0

	for i, j := 0, len(height) - 1; i < j;  {//定义左右两个双指针
		var minHeight int
		if height[i] <= height[j] {
			minHeight = height[i]
			i++
		}else{
			minHeight = height[j]
			j--
		}//分别从左,从右遍历数组,找到最小的高度
		w := (j - i + 1) * minHeight//每次遍历的盛水面积
		if w > max {
			max = w
		}//更新最大面积
	}
	return max

}

在这里插入图片描述
提交截图:
在这里插入图片描述

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值