ブラシの質問のウェブサイト:Leetcode
難易度:中程度
言語:Python
計画:簡単->から中->から難しい。
1.189回転配列
1.1件名:
配列を指定して、配列内の要素k
を。ここで、k
は非負の数です。
-
上級:
できるだけ多くの解決策を考え出します。この問題を解決するには、少なくとも3つの異なる方法があります。
O(1)空間の複雑さを伴うインプレースアルゴリズムを使用してこの問題を解決できますか? -
例1
输入: nums = [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
输入:nums = [-1,-100,3,99], k = 2
输出:[3,99,-1,-100]
解释:
向右旋转 1 步: [99,-1,-100,3]
向右旋转 2 步: [3,99,-1,-100]
1.2思考と分析
この質問は一見非常に短いですが、難易度は中程度なので、もっと注意を払う必要があります。最初にタイトルの一般的な意味を理解します。つまり、配列とk
値を指定してから、最後のk
値を先頭に配置して新しい配列出力を作成します。
まず、配列を2つに分割してから、前後の2つの部分の順番を入れ替えてみようとk
思いた。つまり、配列内のn-k
thインデックス位置をthインデックス位置0
に移動してから、thインデックス位置をthインデックス位置に移動し、以下同様に最後n-k+1
のインデックス位置まで移動し1
ます。ただし、同時に、前の最初のインデックス位置を最初の0
インデックスk
位置に移動し、最初の1
インデックス位置を最初のインデックス位置に移動し、以下同様に最初の位置k+1
まで移動しn-k
ます。
ただし、インデックス位置の値の置き換えが繰り返されるという問題があります。つまり、インデックス位置が置き換えられると、後で繰り返される可能性があるため、最初に空の配列を想定してから、それを入力します。 、元のアレイを直接置換する代わりに。
したがって、完全なコードは次のとおりです(以下はSublime text3で実行するコードです)。
from typing import List
class Solution:
def rotate(self, nums: List[int], k: int) -> None:
"""
Do not return anything, modify nums in-place instead.
"""
n = len(nums)
nums2 = [1]*n
i,j = 0,0
m = k
while m < n:
nums2[m] = nums[j]
if k>0:
nums2[i] = nums[n-k]
k-=1
i+=1
m+=1
j+=1
return nums2
print(Solution().rotate([1,2,3,4,5,6,7],3))
print(Solution().rotate([-1,-100,3,99],2))
出力:
[5, 6, 7, 1, 2, 3, 4]
[3, 99, -1, -100]
[Finished in 0.1s]
一見、結果は正しいように見えます。しかし、実行のためにコードをLeetcodeに入力すると、エラーが表示されました。これは非常に紛らわしく、エラーがどこにあるのかわかりません。出力は上記の元の配列のままですが、ペンとコンピューターの計算はどちらも正しいのですが、なぜ間違っているのですか?
次に、コードのプロンプトに従います
"""
Do not return anything, modify nums in-place instead.
"""
プロンプトは戻り値を必要としないので、それをreturn
削除しましたが、実行はまだ間違っています。
次にコメントを開きます。多くの人が私と同じ問題を抱えています。元の配列を変更する必要があると言う人もいれば、戻り値は役に立たない、何が起こったのかわかりません。
次に、問題を解決する3番目の方法を見てみましょう。使用されるアイデアは、配列を反転することです。
==最初にすべての要素を反転し、末尾のk mod n
要素を配列の先頭に移動します(ここでのモジュロは、タイトルで指定されたkがnより大きい可能性があり、その反転はk
モジュロの2次であるためです)。次に、間隔を反転し[0, k mod n-1]
ます。間隔の要素と[k mod n, n-1]
要素を使用できます。
Pythonの関数reverse()
は最初の数個の数値の反転を指定していないため(または私にはわからないかもしれません)、最初に反転関数を自分で定義する必要があります。
def reverse(self, nums):
n = len(nums)-1
i = 0
while i<n:
j = nums[i]
nums[i] = nums[n]
nums[n] = j
i+=1
n-=1
return nums
次にrotate()
、関数でそれを呼び出してフリップを実装します。完全なコードは次のようになります。
class Solution:
def rotate(self, nums: List[int], k: int) -> None:
"""
Do not return anything, modify nums in-place instead.
"""
k %=len(nums)
self.nums = self.reverse(nums)
self.nums[0:k] = self.reverse(nums[0:k])
self.nums[k:] = self.reverse(nums[k:])
print(nums)
def reverse(self,nums):
n = len(nums) -1
i = 0
while i < n:
j = nums[i]
nums[i] = nums[n]
nums[n] = j
i+=1
n-=1
return nums
実行結果は次のように渡されます。渡されます
が、アルゴリズムは最適ではありません。
1.3まとめ
この質問自体を考えることは難しくなく、答えることはできますが、要件に応じて答えることはより困難です。たとえば、以前の方法を逆にすることはできますが、実行中のメモリの問題を考慮しなかったため、送信に問題が発生します。したがって、問題解決のアルゴリズムのアイデアに従ってのみ解決できます。