Golang面试考题记录 ━━ 两个数组的交集 II 双100%及goto、continue和break的用法

===问:

给定两个数组,编写一个函数来计算它们的交集。

示例 1:

输入: nums1 = [1,2,2,1], nums2 = [2,2]
输出: [2,2]

示例 2:

输入: nums1 = [4,9,5], nums2 = [9,4,9,8,4]
输出: [4,9]

说明:

  • 输出结果中每个元素出现的次数,应与元素在两个数组中出现的次数一致。
  • 我们可以不考虑输出结果的顺序。

进阶:

  • 如果给定的数组已经排好序呢?你将如何优化你的算法?
  • 如果 nums1 的大小比 nums2 小很多,哪种方法更优?
  • 如果 nums2 的元素存储在磁盘上,磁盘内存是有限的,并且你不能一次加载所有的元素到内存中,你该怎么办?

===答:

方法一:执行11.56%|90.44% ,内存94.59%
比较鸡贼,因为知道测试数据没有负数,因此用了负数替换,理论我想应该比append()快点吧~

func intersect1(nums1 []int, nums2 []int) []int {
	numsA := nums1
	numsB := nums2

	if len(nums1) < len(nums2) {
		numsA = nums2
		numsB = nums1
	}

	var r []int

	for _, v := range numsA {
		for i, y := range numsB {
			if v == y {
				r = append(r, v)
				numsB[i] = -1
				//退出一层
				break
			}
		}

	}
	return r
}

方法二:执行100.00%|90.44% ,内存100.00%|94.59%
看了一下内存排名第一的用了递归。。。

func intersect2(nums1 []int, nums2 []int) []int {
	numsA := nums1
	numsB := nums2

	if len(nums1) < len(nums2) {
		numsA = nums2
		numsB = nums1
	}

	var r []int

	for _, v := range numsA {
		// 本局意义不大,系统发现numsB为空值亦不会循环
		/*if len(numsB) == 0 {
			return r
		}*/
		for i, y := range numsB {
			if v == y {
				r = append(r, v)
                //去除一个元素
				numsB = append(numsB[:i], numsB[i+1:]...)
				//退出一层
				break
			}
		}

	}

	return r
}

===知识点

本题别的没什么好总结的,主要是一个知识点要强化一下,那就是breakcontinuegoto的用法
参考:golang跳转语句goto,break,continue的使用及区别

goto

goto语句可以无条件地转移到过程中指定的行。 通常与条件语句配合使用。可用来实现条件转移, 构成循环,跳出循环体等功能。
在结构化程序设计中一般不主张使用goto语句, 以免造成程序流程的混乱
goto对应(标签)既可以定义在for循环前面,也可以定义在for循环后面,当跳转到标签地方时,继续执行标签下面的代码。

func goto1() {
    // 放在for前面,此例会一直循环下去
    Loop:
    fmt.Println("test")
    for a:=0;a<5;a++{
        fmt.Println(a)
        if a>3{
            goto Loop
        }
    }
}

func goto2() {
    for a:=0;a<5;a++{
        fmt.Println(a)
        if a>3{
            goto Loop
        }
    }
    // 放在for后边,跳出结束
    Loop:
    fmt.Println("test")
}

break

在没有使用loop标签的时候break只是跳出了第一层for循环
使用标签后跳出到指定的标签,break只能跳出到之前,
如果将Loop标签放在后边则会报错
break标签只能用于for循环,跳出后不再执行标签对应的for循环

func breakTest() {
//正常执行
Loop:
	for j := 0; j < 3; j++ {
		// 出错
		// Loop:
		fmt.Println(j)
		for a := 0; a < 5; a++ {
			// 出错
			// Loop:
			fmt.Println(a)
			if a > 3 {
				// 出错
				// Loop:
				break Loop
			}
		}
	}
// 出错
// Loop:
	fmt.Println("end")
}
/*
输出:
0
0
1
2
3
4
end
*/

continue

continue就是直接进入下一次循环。break是跳出整个循环,标签的使用类似于break

// 只能放在这个位置,其余位置和break一样,皆出错
loop:
	for j := 0; j < 3; j++ {
		fmt.Println(j)
		for a := 0; a < 5; a++ {
			fmt.Println(a)
			if a > 3 {
				continue loop
			}
		}
	}
	fmt.Println("end")

/*
输出:
0
0
1
2
3
4
1
0
1
2
3
4
2
0
1
2
3
4
end
*/

goto语句本身就是做跳转用的,而break和continue是配合for使用的。所以goto的使用不限于for,通常与条件语句配合使用
在for循环中break和continue可以配合标签使用。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值