Gopher面试中的Coding

brantou · · 5544 次点击 · · 开始浏览    
这是一个创建于 的文章,其中的信息可能已经有所发展或是发生改变。

从四月份下半月开始,陆陆续续面试了几家公司,都是golang的岗位。每一次面试,侧重点都会有不同,有的会直接给过来一道试题, 然后边解题,边讲述自己的思路,然后面试官根据你的思路和你交流沟通;有的呢,让讲述自己最近做过的项目,遇到的难点, 自己怎么解决的问题思路,而无独有偶的呢,这样的面试中,都要需要展示编码能力。这篇文章就把自己最近面试中遇到的每一个编程问题, 分三步阐述出来:问题描述,解题思路,实际编程。

交替打印数字和字母

问题描述

使用两个 goroutine 交替打印序列,一个 goroutinue 打印数字, 另外一个goroutine打印字母, 最终效果如下 12AB34CD56EF78GH910IJ

解题思路

问题很简单,使用 channel 来控制打印的进度。使用两个 channel ,来分别控制数字和字母的打印序列, 数字打印完成后通过 channel 通知字母打印, 字母打印完成后通知数字打印,然后周而复始的工作。

实际编码<a id="sec-1-3"></a>

runtime.GOMAXPROCS(runtime.NumCPU())
chan_n := make(chan bool)
chan_c := make(chan bool, 1)
done := make(chan struct{})

go func() {
  for i := 1; i < 11; i += 2 {
    <-chan_c
    fmt.Print(i)
    fmt.Print(i + 1)
    chan_n <- true
  }
}()

go func() {
  char_seq := []string{"A","B","C","D","E","F","G","H","I","J","K"}
  for i := 0; i < 10; i += 2 {
    <-chan_n
    fmt.Print(char_seq[i])
    fmt.Print(char_seq[i+1])
    chan_c <- true
  }
  done <- struct{}{}
}()

chan_c <- true
<-done

代码执行结果:

12AB34CD56EF78GH910IJ

随机抽奖<a id="sec-2"></a>

问题描述<a id="sec-2-1"></a>

用户随机抽奖,数据结构如下所示:

// map中,key代表名称,value代表成交单数
var users map[string]int64 = map[string]int64{
  "a": 10,
  "b": 6,
  "c": 3,
  "d": 12,
  "f": 1,
}

解决思路

从map中选取随机用户,拿到这个编码问题,有点懵逼,但仔细一想,只需把关注用户的区间,转变一下数据结构即解题。 把map转成array,思考起来就简单多了,原有问题变成了从0至n-1中选取一个数字,数字对应的用户即中奖用户。

实际编码

package main

import (
  "fmt"
  "math/rand"
  "time"
)

func GetAwardUserName(users map[string]int64) (name string) {
  sizeOfUsers := len(users)
  award_index := rand.Intn(sizeOfUsers)

  var index int
  for u_name, _ := range users {
    if index == award_index {
      name = u_name
      return
    }
    index += 1
  }
  return
}

func main() {
  var users map[string]int64 = map[string]int64{
    "a": 10,
    "b": 6,
    "c": 3,
    "d": 12,
    "e": 20,
    "f": 1,
  }

  rand.Seed(time.Now().Unix())
  award_stat := make(map[string]int64)
  for i := 0; i < 1000; i += 1 {
    name := GetAwardUserName(users)
    if count, ok := award_stat[name]; ok {
      award_stat[name] = count + 1
    } else {
      award_stat[name] = 1
    }
  }

  for name, count := range award_stat {
    fmt.Printf("user: %s, award count: %d\n", name, count)
  }

  return
}

代码执行结果:

user: f, award count: 178
user: d, award count: 152
user: b, award count: 159
user: e, award count: 182
user: c, award count: 170
user: a, award count: 159

权重抽奖

问题描述

数据结构和上面一致,只是问题发生变化,需要更加用户的成单数来抽奖,用户成单越多,中奖概率越高,结构如下所示:

// map中,key代表名称,value代表成交单数
var users map[string]int64 = map[string]int64{
  "a": 10,
  "b": 6,
  "c": 3,
  "d": 12,
  "f": 1,
}

解决思路

这一题是上一题的延伸,加了订单数进去,做为权重来为用户抽奖。此题和上面的问题如此的相似,可把上面的问题, 理解成所有的用户权重都相同的抽奖,而此题是权重不同的抽奖。解决此问题,依旧是把map转为数组来思考, 把各用户的权重,从前到后依次拼接到数轴上,数轴的起点到终点即时中奖区间,而随机数落到的那个用户的区间,那个用户即为中奖用户。

实际编码<a id="sec-3-3"></a>

package main

import (
  "fmt"
  "math/rand"
  "time"
)

func GetAwardUserName(users map[string]int64) (name string) {
  type A_user struct {
    Name   string
    Offset int64
    Num    int64
  }

  a_user_arr := make([]*A_user, 0)
  var sum_num int64
  for name, num := range users {
    a_user := &A_user{
      Name:   name,
      Offset: sum_num,
      Num:    num,
    }
    a_user_arr = append(a_user_arr, a_user)
    sum_num += num
  }

  award_num := rand.Int63n(sum_num)

  for index, _ := range a_user_arr {
    a_user := a_user_arr[index]
    if a_user.Offset+a_user.Num > award_num {
      name = a_user.Name
      return
    }
  }
  return
}

func main() {
  var users map[string]int64 = map[string]int64{
    "a": 10,
    "b": 5,
    "c": 15,
    "d": 20,
    "e": 10,
    "f": 30,
  }

  rand.Seed(time.Now().Unix())
  award_stat := make(map[string]int64)
  for i := 0; i < 10000; i += 1 {
    name := GetAwardUserName(users)
    if count, ok := award_stat[name]; ok {
      award_stat[name] = count + 1
    } else {
      award_stat[name] = 1
    }
  }

  for name, count := range award_stat {
    fmt.Printf("user: %s, award count: %d\n", name, count)
  }

  return
}

代码执行结果:

user: c, award count: 1667
user: f, award count: 3310
user: e, award count: 1099
user: d, award count: 2276
user: b, award count: 549
user: a, award count: 1099

总结

问题一来自一家公司 , 侧重于语言特性;问题二三来自另外一家公司 ,侧重于解决问题的思路;本人更喜欢第二种,很有启发性。 我之后会把其他自己认为比较有趣的编程任务,整理到此篇文章中,敬请期待。


有疑问加站长微信联系(非本文作者)

本文来自:简书

感谢作者:brantou

查看原文:Gopher面试中的Coding

入群交流(和以上内容无关):加入Go大咖交流群,或添加微信:liuxiaoyan-s 备注:入群;或加QQ群:692541889

5544 次点击  ∙  2 赞  
加入收藏 微博
被以下专栏收入,发现更多相似内容
上一篇:GO语言之接口
3 回复  |  直到 2020-02-13 08:45:03
暂无回复
添加一条新回复 (您需要 登录 后才能回复 没有账号 ?)
  • 请尽量让自己的回复能够对别人有帮助
  • 支持 Markdown 格式, **粗体**、~~删除线~~、`单行代码`
  • 支持 @ 本站用户;支持表情(输入 : 提示),见 Emoji cheat sheet
  • 图片支持拖拽、截图粘贴等方式上传