为了账号安全,请及时绑定邮箱和手机立即绑定

这是一个合理且惯用的 GoLang 循环移位实现吗?

这是一个合理且惯用的 GoLang 循环移位实现吗?

Go
红糖糍粑 2021-11-15 15:52:36
任何人都可以评论这是否是在 Go中实现整数数组循环移位的合理且惯用的方法?(我故意选择不使用按位运算。)如何改进?package mainimport "fmt"func main() {    a := []int{1,2,3,4,5,6,7,8,9,10}    fmt.Println(a)    rotateR(a, 5)    fmt.Println(a)    rotateL(a, 5)    fmt.Println(a)}func rotateL(a []int, i int) {    for count := 1; count <= i; count++ {        tmp := a[0]        for n := 1;n < len(a);n++ {            a[n-1] = a[n]        }        a[len(a)-1] = tmp    }}func rotateR(a []int, i int) {    for count := 1; count <= i; count++ {        tmp := a[len(a)-1]        for n := len(a)-2;n >=0 ;n-- {            a[n+1] = a[n]        }        a[0] = tmp    }}
查看完整描述

3 回答

?
慕田峪4524236

TA贡献1875条经验 获得超5个赞

一次旋转切片一个位置,并重复以获得所需的总旋转量意味着需要的时间与旋转距离×切片长度成正比。通过将每个元素直接移动到其最终位置,您可以按与切片长度成比例的时间进行此操作。


这段代码比你所拥有的要复杂一些,你需要一个 GCD 函数来确定通过切片的次数:


func gcd(a, b int) int {

    for b != 0 {

        a, b = b, a % b

    }


    return a

}


func rotateL(a []int, i int) {


    // Ensure the shift amount is less than the length of the array,

    // and that it is positive.

    i = i % len(a)

    if i < 0 {

        i += len(a)

    }


    for c := 0; c < gcd(i, len(a)); c++ {


        t := a[c]


        j := c


        for {

            k := j + i

            // loop around if we go past the end of the slice

            if k >= len(a) {

                k -= len(a)

            }

            // end when we get to where we started

            if k == c {

                break

            }

            // move the element directly into its final position

            a[j] = a[k]

            j = k

        }


        a[j] = t

    }

}

旋转大小的片升权由p位置相当于旋转它留下由升- p位置,这样你就可以简化您的rotateR使用功能rotateL:


func rotateR(a []int, i int) {

    rotateL(a, len(a) - i)

}


查看完整回答
反对 回复 2021-11-15
?
胡子哥哥

TA贡献1825条经验 获得超6个赞

您的代码适合就地修改。


不明白你所说的按位运算是什么意思。也许这


package main


    import "fmt"


    func main() {

        a := []int{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}

        fmt.Println(a)

        rotateR(&a, 4)

        fmt.Println(a)

        rotateL(&a, 4)

        fmt.Println(a)

    }


    func rotateL(a *[]int, i int) {

        x, b := (*a)[:i], (*a)[i:]

        *a = append(b, x...)

    }


    func rotateR(a *[]int, i int) {

        x, b := (*a)[:(len(*a)-i)], (*a)[(len(*a)-i):]

        *a = append(b, x...)

    }

代码有效https://play.golang.org/p/0VtiRFQVl7


这在 Go 词汇中称为重新切片。权衡是在您的代码段中处理和循环与在此动态分配。这是您的选择,但在将 10000 个元素阵列移动一个位置的情况下,重新切片看起来便宜得多。


查看完整回答
反对 回复 2021-11-15
?
幕布斯6054654

TA贡献1876条经验 获得超7个赞

我喜欢 Uvelichitel 解决方案,但如果您想要 O(n) 复杂度的模算术


package main

func main(){

   s := []string{"1", "2", "3"}

   rot := 5

   fmt.Println("Before RotL", s)

   fmt.Println("After RotL", rotL(rot, s))

   fmt.Println("Before RotR", s)

   fmt.Println("After RotR", rotR(rot,s))


}

func rotL(m int, arr []string) []string{

     newArr := make([]string, len(arr))


     for i, k := range arr{

         newPos := (((i - m) % len(arr)) + len(arr)) % len(arr)

         newArr[newPos] = k

     }


     return newArr

}


func rotR(m int, arr []string) []string{


     newArr := make([]string, len(arr))


     for i, k := range arr{

         newPos := (i + m) % len(arr)

         newArr[newPos] = k

      }

      return newArr

}


查看完整回答
反对 回复 2021-11-15
  • 3 回答
  • 0 关注
  • 252 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信