Gopher面試中的Coding

715001687 7年前發布 | 23K 次閱讀 Google Go/Golang開發 Golang

從四月份下半月開始,陸陸續續面試了幾家公司,都是golang的崗位。每一次面試,側重點都會有不同,有的會直接給過來一道試題, 然后邊解題,邊講述自己的思路,然后面試官根據你的思路和你交流溝通;有的呢,讓講述自己最近做過的項目,遇到的難點, 自己怎么解決的問題思路,而無獨有偶的呢,這樣的面試中,都要需要展示編碼能力。這篇文章就把自己最近面試中遇到的每一個編程問題, 分三步闡述出來:問題描述,解題思路,實際編程。

交替打印數字和字母

問題描述

使用兩個 goroutine 交替打印序列,一個 goroutinue 打印數字, 另外一個goroutine打印字母, 最終效果如下 12AB34CD56EF78GH910IJ

解題思路

問題很簡單,使用 channel 來控制打印的進度。使用兩個 channel ,來分別控制數字和字母的打印序列, 數字打印完成后通過 channel 通知字母打印, 字母打印完成后通知數字打印,然后周而復始的工作。

實際編碼

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

隨機抽獎

問題描述

用戶隨機抽獎,數據結構如下所示:

// 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轉為數組來思考, 把各用戶的權重,從前到后依次拼接到數軸上,數軸的起點到終點即時中獎區間,而隨機數落到的那個用戶的區間,那個用戶即為中獎用戶。

實際編碼

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

總結

問題一來自一家公司 , 側重于語言特性;問題二三來自另外一家公司 ,側重于解決問題的思路;本人更喜歡第二種,很有啟發性。 我之后會把其他自己認為比較有趣的編程任務,整理到此篇文章中,敬請期待。



來自:http://www.jianshu.com/p/268068e786b8

 本文由用戶 715001687 自行上傳分享,僅供網友學習交流。所有權歸原作者,若您的權利被侵害,請聯系管理員。
 轉載本站原創文章,請注明出處,并保留原始鏈接、圖片水印。
 本站是一個以用戶分享為主的開源技術平臺,歡迎各類分享!