博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Golang面试考题记录 ━━ 旋转数组 ~~ 执行95.39%和内存100%的抉择
阅读量:4116 次
发布时间:2019-05-25

本文共 2350 字,大约阅读时间需要 7 分钟。

===问:

给定一个数组,将数组中的元素向右移动 k 个位置,其中 k 是非负数。

示例 1:

输入:

[1,2,3,4,5,6,7] 和 k = 3
输出:
[5,6,7,1,2,3,4]
解释:
向右旋转 1 步: [7,1,2,3,4,5,6]
向右旋转 2 步: [6,7,1,2,3,4,5]
向右旋转 3 步: [5,6,7,1,2,3,4]

示例 2:

输入:

[-1,-100,3,99] 和 k = 2
输出:
[3,99,-1,-100]
解释:
向右旋转 1 步: [99,-1,-100,3]
向右旋转 2 步: [3,99,-1,-100]

说明:

  • 尽可能想出更多的解决方案,至少有三种不同的方法可以解决这个问题。
  • 要求使用空间复杂度为 O(1) 的 原地 算法。

===答:

方法一:执行34.66%,内存16.98%

创建一个切片temp,遍历nums,根据条件将值一个一个放入temp

func rotate1(nums []int, k int) {
l := len(nums) //新建一个临时切片 temp := make([]int, l, l) // 去掉所有元素都循环过的次数 k = k % l // fmt.Println(k) //不需要循环直接跳出 if k == 0 {
return } for i := range nums {
j := i + k if j < l {
temp[j] = nums[i] } else if j > l {
temp[j-l] = nums[i] } else {
temp[0] = nums[i] } // fmt.Println(temp, nums[i]) // temp = append(temp[l-1:], temp[:l-1]...) } //还给原切片 for i, v := range temp {
nums[i] = v } // fmt.Printf("%T %v\n", nums, nums)}

方法二:执行95.39%,内存9.43%

利用内置函数append()实现,但由于每次append(),内存地址都会改变,因此也需要启用一个临时切片temp
只能使用append(nums[:0],temp...)这种形式来保证nums的地址不会改变。

func rotate2(nums []int, k int) {
l := len(nums) k = k % l if k == 0 {
return } // 效果与下面的评测结果一致 // nums = append(nums[:0], (append(nums[l-k:], nums[:l-k]...))...) //每一次append,内存地址都会改变, //新建一个临时切片 temp = append(nums[l-k:], nums[:l-k]...) //还给原切片 nums = append(nums[:0], temp...)}

方法三:执行8.57%,内存64.15%

这个思路就比较简单了,nums元素的前一个值替换后一个,最后的值替换第一个。
这个方法都在nums中操作,由于少了一个临时切片,内存开销大大降低。

func rotate3(nums []int, k int) {
l := len(nums) k %= l // fmt.Println(k) if k == 0 {
return } var temp int for i := 0; i < k; i++ {
temp = nums[l-1] for j := l - 1; j >= 0; j-- {
if j == 0 {
nums[0] = temp } else {
nums[j] = nums[j-1] } } }}

方法四:执行18.24%,内存100%

这个方法参考了内存占用排名第一的代码,与方法三几乎无疑,只是多了一个临时变量,并将nums[j] = num[j-1]替换成了nums[j]=t1,利用变量t1t2之间进行替换,而不像方法三中切片直接nums[n]=nums[n-1]交换值,虽然表面上多了一个变量,实际内存却占用更小。

func rotate4(nums []int, k int) {
l := len(nums) k %= l // fmt.Println(k) if k == 0 {
return } var t1, t2 int for i := 0; i < k; i++ {
t1 = nums[l-1] for j := 0; j < l; j++ {
t2 = nums[j] nums[j] = t1 t1 = t2 } }}

===解:

这道题到手的时候一度感觉特别简单,结果四个解题方法做了一天。。。真是够菜的!

其中注意的地方主要有:

  1. 虽然有append(nums[:0],temp)这种形式来防止重置内存地址(前提是temp内的元素个数与nums中的一致),但这也提醒我们实际使用append()时需密切注意内存的变化。
  2. 在大数据量的切片中更新值,某些情况宁可使用一个临时变量来存值,而不要用索引的方法互相交换值(方法四)
  3. 循环的思路要多多变换,比如方法一和方法三的循环相比,一看就知道方法一够菜!~~哈

转载地址:http://evkpi.baihongyu.com/

你可能感兴趣的文章
14个前端开发人员必备的有用工具
查看>>
8个优质jquery分页插件
查看>>
来一起用 Vue3 做个飞机大战游戏
查看>>
12个方便易用的jquery表单验证插件
查看>>
JavaScript函数中this的4种绑定策略
查看>>
JavaScript this常见指向问题
查看>>
适用于所有Web开发人员的6个有用的GitHub存储库
查看>>
34种你需要了解的JavaScript优化技术
查看>>
网页设计中的图标
查看>>
5条快速优化博客的SEO技巧
查看>>
移动端h5网页调用支付宝支付接口
查看>>
字节、百度面试真题,你不会可就凉凉了(内附答案)
查看>>
5种设计有效按钮的最佳做法
查看>>
12种增强CSS技能并加快开发速度的资源
查看>>
如何让HTML5数字输入仅接受整数?
查看>>
改善网页性能的5种方法
查看>>
9个实用的JavaScript开发技巧,你必须知道一下
查看>>
如何使丑陋的Arial看起来好看
查看>>
10个实现炫酷UI设计效果的CSS生成工具
查看>>
如何通过使用CSS实现渐变文字的效果
查看>>