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

这是一个合理且惯用的GoLang循环移位实现吗?,go,Go,有人能评论一下这是否是一种在Go中实现整数数组的合理且惯用的方法吗?(我故意选择不使用逐位运算。) 如何改进 package main import "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

有人能评论一下这是否是一种在Go中实现整数数组的合理且惯用的方法吗?(我故意选择不使用逐位运算。)

如何改进

package main

import "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
    }
}
主程序包
输入“fmt”
func main(){
a:=[]int{1,2,3,4,5,6,7,8,9,10}
fmt.Println(a)
旋转器(a,5)
fmt.Println(a)
罗泰尔(a,5)
fmt.Println(a)
}
func rotateL(a[]int,i int){

对于count:=1;count您的代码可以进行就地修改

我不清楚你所说的位运算是什么意思。也许是这样

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...)
    }
代码工作


这在Go词汇表中称为重新选择。折衷方法是在代码段中处理和循环,而不是动态分配。这是您的选择,但如果将10000个元素数组按一个位置移动,重新选择看起来要便宜得多。

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

这比您的操作要复杂一些,您需要一个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
    }
}

我喜欢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
}

对我来说似乎很好,也很习惯。我认为唯一更好的方法是确保如果我比len(a)大,那么旋转的次数就不会超过需要的次数。如果您不介意分配一个由
I
元素组成的临时数组,只需执行一些
copy()
操作。它正确处理重叠的源和目标。
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
}