思路是利用map的映射关系来求交并集
package main
import "fmt"
//假设两个集合没有重复元素
//slice1 = [1, 2, 3, 4, 5]
//slice2 = [3, 4, 5, 6, 7]
func intersection(slice1 []int,slice2 []int) []int{
//1.
m:=make(map[int]int)
for _,val:=range slice1{
m[val]=1
}
//2.
var ans []int
for _,val:=range slice2{
times := m[val]
if times!=0 {
ans=append(ans,val)
}
}
return ans
}
func union_set(slice1 []int,slice2 []int) []int{
//1.
m:=make(map[int]int)
for _,val:=range slice1{
m[val]=1
}
//2.
for _,val:=range slice2{
times:=m[val]
if times==0 {
slice1=append(slice1,val)
}
}
return slice1
}
func main() {
intersection:=intersection([]int{1,2,3,4,5},[]int{3,4,5,6,7})
UnionSet:=union_set([]int{1, 2, 3, 4, 5}, []int{3, 4, 5, 6, 7})
for _,val:=range intersection{
fmt.Println(val)
}
for _,val:=range UnionSet{
fmt.Println(val)
}
}
func assigned(){
slice := []int{0, 1, 2, 3, 4, 5, 6, 7, 8, 9}
s1 := slice[2:5] // slice[2,3,4,x5,x6,x7,x8,x9]
s2 := s1[2:6:7] // s1[4,5,6,7,x8]
s2 = append(s2, 100) // s1[4,5,6,7,100]
s2 = append(s2, 200) // ns1[4,5,6,7,100,200]
s1[2] = 20 // slice[2,3,20,x5,x6,x7,x8,x9]
fmt.Println(s1) //[2 3 20]
fmt.Println(s2) //[4 5 6 7 100 200]
fmt.Println(slice) //[0 1 2 3 20 5 6 7 100 9]
}
1.切片底层原理,切片其实就是一个对底层数组的一种有限的访问方式的抽象,每个切片都有指针字段,长度字段,容量字段,通过这三个字段来控制对底层数组的访问
2.切片传递给函数使用的是值传递,也就是实参到形参完成了一次切片复制,这是由于切片本身不是数组,复制一份依然指向原来的数组,所以依然可以对原来的底层数组进行 *** 作
3.如果是指针传递那就是传递原来切片的指针,函数通过指针访问原来的切片再访问底层数组,这样对于大的数据结构比较合适,由于切片本身很小,所以不如直接值传递,复制一份
思考:复杂度、内存空间大小,如何分配内存。栈空间堆空间
1.时间复杂度就相当于遍历一整颗树o(n)
2.内存大小,由于每一层递归只用到常数级别内存,假设这颗树深度n,那么递归深度为n,所以系统栈所用空间为o(n)
3.每一层函数的局部变量以及递归参数信息的保存都是在系统栈中,所以设计栈空间,但是由于没有对象的创建,所以没有堆空间的分配
type MyStruct struct {
Name string
DownStream []*MyStruct
}
//implement me
func isExist(root *MyStruct, name string) bool {
//1.
if root==nil {
return false
}
//2.
if root.Name==name {
return true
}
//3.
for _,son:=range root.DownStream{
if isExist(son,name)==true {
return true
}
}
return false
}
package main
import "fmt"
func func1(l1 []int,ch chan string){
for _, val := range l1 {
if "ok"==<-ch{
fmt.Println(val)
ch<-"ok"
}
}
//这个最后结束的接收,是由于func2的最后一个ch<-"ok"如果没有一个接收会阻塞
//那么func2的协程就没办法结束,造成死锁
<-ch
}
func func2(l2 []int,ch chan string){
//这个发送是为了先打印l1
ch<-"ok"
for _, val := range l2 {
if "ok"==<-ch{
fmt.Println(val)
//容易死锁
ch<-"ok"
}
}
}
func main() {
// 起协程并发轮流打印两个数组内容
// output
// 1,3,2,4,3,5,4,6
l1 := []int{1,2,3,4}
l2 := []int{3,4,5,6}
ch:=make(chan string)
go func1(l1,ch)
func2(l2,ch)
}
1.c := make(chan int) 和 c1 := make(chan int, 1) 有什么区别?
前者是无缓冲通道,后者是缓冲区大小为1的通道
2.起一个goroutine,怎么从main goroutine杀掉启动的goroutine?
思路就是使用一个通道作为协程关闭的标志,当main协程执行close(done)时,其他协程就会接收到一个空值进而关闭
package main
import (
"fmt"
"time"
)
func funcName(done chan string){
for true {
select {
case <-done:
return
default:
fmt.Println("1")
}
}
}
func main() {
done:=make(chan string)
go funcName(done)
go funcName(done)
go funcName(done)
time.Sleep(time.Second*3)
close(done)
time.Sleep(time.Second*3)
fmt.Println("main协程")
}
Golang中有继承吗?实现一个Son类继承Father
Golang中没有继承,结构体与结构体之间只能采用以往oop中的组合关系,即将一个结构体注入另外一个结构体中
package main
import "fmt"
type Father struct {
name_f string
}
func (f Father)show(){
fmt.Println("my name is "+f.name_f)
}
type Son struct {
Father
name_s string
}
//少写一个show可以测试show方法在有没有绑定到Son中来
func (s Son)show(){
fmt.Println("my name is "+s.name_s)
}
func main() {
father:=Father{"father"}
son:=Son{father,"son"}
//Son可以直接取到father的属性,由于Father是匿名注入的方式
fmt.Println(son.name_f)
father.show()
son.show()
}
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)