在Go语言中,如何遍历一个几乎递增的序列而避免索引越界?

huangapple go评论85阅读模式
英文:

Almost increasing sequence in Go: how to loop avoiding index out of bound?

问题

所以我正在尝试通过做一些算法挑战来学习Go语言,我目前正在做的一个挑战叫做"almost increasing sequence"。

指令如下:

给定一个整数序列作为数组,确定是否可以通过从数组中移除不超过一个元素来获得严格递增的序列。

  • 对于 sequence = [1, 3, 2, 1],输出应为 almostIncreasingSequence(sequence) = false

  • 这个数组中没有一个元素可以被移除以获得严格递增的序列。

  • 对于 sequence = [1, 3, 2],输出应为 almostIncreasingSequence(sequence) = true

  • 我们可以从数组中移除3,得到严格递增的序列[1, 2]。或者我们可以移除2,得到严格递增的序列[1, 3]。

如果可以移除一个元素以获得严格递增的序列,则函数必须返回true,否则返回false。

我已经用TypeScript完成了这个挑战,不难。但是我想用Go重新编写它,但是我发现在Go中避免"index out of range"错误有点棘手。以下是我目前的代码:

func almostIncreasingSequence(a []int) bool {
    var count int = 0

    for i := 0; i < len(a); i++ {
        if a[i] <= a[i-1] {
            count++
            if (a[i] <= a[i-2]) && (a[i+1] <= a[i-1]) {
                return false
            }
        }
    }

    return count <= 1
}

这是我从TypeScript直接转换过来的代码,在TypeScript中它可以正常工作,但是你可以很容易地从我的Go代码中注意到"index out of range"错误发生在迭代时的if a[i] <= a[i-1]

在编写Go代码时,有没有什么技巧可以避免比较索引ii - 1i + 1时出现"index out of range"错误?

提前感谢!

英文:

So I am trying to learn Go by doing some algorithm challenges, and the one I am currently on is called almost increasing sequence.

The instruction looks like:

>Given a sequence of integers as an array, determine whether it is possible to obtain a strictly increasing sequence by removing no more than one element from the array.

>- For sequence = [1, 3, 2, 1], the output should be
almostIncreasingSequence(sequence) = false;

>There is no one element in this array that can be removed in order to get a strictly increasing sequence.

>- For sequence = [1, 3, 2], the output should be
almostIncreasingSequence(sequence) = true.

>We can remove 3 from the array to get the strictly increasing sequence [1, 2]. Alternately, we can remove 2 to get the strictly increasing sequence [1, 3].

>The function must return true if it is possible to remove one element from the array in order to get a strictly increasing sequence, otherwise return false.

I have finished this in Typescript already, it was not hard. But I am trying to write it again in Go, but I found it is kinda tricky to avoid index out of range error in Go. Here is my code so far:

func almostIncreasingSequence(a []int) bool {
    var count int = 0

	for i := 0; i &lt; len(a); i++ {
    	if a[i] &lt;= a[i-1] {
	    	count++
		    if (a[i] &lt;= a[i-2]) &amp;&amp; (a[i+1] &lt;= a[i-1]) {
			    return false
		    }
	    }
    }

    return count &lt;= 1
}

This is what I literally converted what I wrote in Typescript and it works fine with Typescript, but as you can easily notice from my Go code index out of range error occurs when as it iterates, if a[i] &lt;= a[i-1].

Are there any tricks to compare an element at index i and i - 1 or i + 1 avoiding index out of range error when write code in Go?

Thanks in advance!

答案1

得分: 1

这不是一个技巧。你正在从0(第一个元素)循环到数组的长度减一,或者上限。当i == len(a) - 1时,a[i+1]将超过数组的长度。如果数组中只有3个项,它们的索引将是012len(a)给出的是3i < len(a)的结果是02

你还在第一次迭代中从i中减去了一个值,这基本上是在询问编译器if a[0] <= a[-1],这导致a[-1]超出了数组的边界。你在a[i] <= a[i-2]中再次这样做。

我相当确定你只需要这样的代码:

func almostIncreasingSequence(a []int) bool {
	count := 0 // :=是简写形式。只要它在函数内部,它基本上等同于var。它还推断出类型。
	l :=  len(a) - 1
	for i := 0; i < l; i++ {
		if a[i] > a[i+1] {
			count++
		}
	}
	r := count <= 1
	fmt.Println(a, r)
	return r
}

结果为:

[1 3 2 1] false
[1 3 2] true

https://play.golang.org/p/8d_3a_PMM2C

如果性能很重要且数组可能很大,请添加对count的检查:

		if a[i] > a[i+1] {
			count = count + 1
            if(count > 1) {
            	return false;
			}
		}

它在JavaScript中工作的原因是由于Undefined的处理方式。

<!-- begin snippet: js hide: false console: true babel: false -->

<!-- language: lang-js -->

console.log(1 < undefined)
console.log(0 < undefined)

const array = []

console.log(array[0] < 0)
console.log(array[-1] < 0)
console.log(array[9999] < 0)

<!-- end snippet -->

由于它设计的目标,JavaScript是一种非常宽容的语言。

英文:

It isn't a trick. You are looping from 0 (first element) through the length of the array minus one, or upper bounds. When i == len(a) - 1 then a[i+1] is going to exceed the length of the array. If there are only 3 items in it, their indexes will be 0, 1, 2. len(a) gives you 3. i &lt; len(a) results in 0 through 2.

You are also subtracting from i on the first iteration which is basically asking the compiler if a[0] &lt;= a[-1] which results in a[-1] being outside of the boundaries of the array. You do so again with a[i] &lt;= a[i-2].

I'm fairly certain you just need something like:

func almostIncreasingSequence(a []int) bool {
	count := 0 // := is shorthand. So long as it is within a func it is basically equiv of var. It also infers the type.
	l :=  len(a) - 1
	for i := 0; i &lt; l; i++ {
		if a[i] &gt; a[i+1] {
			count++
		}
	}
	r := count &lt;= 1
	fmt.Println(a, r)
	return r
}

Results in:

[1 3 2 1] false
[1 3 2] true

https://play.golang.org/p/8d_3a_PMM2C

If performance is important and the array could be large, add a check for count:

		if a[i] &gt; a[i+1] {
			count = count + 1
            if(count &gt; 1) {
            	return false;
			}
		}

The reason it worked in JavaScript is due to how Undefined is treated.

<!-- begin snippet: js hide: false console: true babel: false -->

<!-- language: lang-js -->

console.log(1 &lt; undefined)
console.log(0 &lt; undefined)

const array = []

console.log(array[0] &lt; 0)
console.log(array[-1] &lt; 0)
console.log(array[9999] &lt; 0)

<!-- end snippet -->

It is an incredibly forgiving language due to the terrain it was devised for.

huangapple
  • 本文由 发表于 2020年8月29日 13:19:14
  • 转载请务必保留本文链接:https://go.coder-hub.com/63643717.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定