??ダブルポインタに直面しているものに、二重のポインタとは何である 二つの数と速度のポインタ演算二つの合計リストに-ダブルポインタ質問の創始 クイックソート&マージソート
•ダブルポインタと同じ方向のダブルポインタが直面している •にほぼすべてのバリエーションを二つ合計パーティション• ••クイック3つのセクションに分かれて2つの部分に選択の分割• •あなたが聞いたことがない何か(ただし、面接の検査)アルゴリズムをソート
典型的な問題は、ダブルポインタ文字列フリッピングの問題に直面しています。
Pythonの:
"""
@param s: a list of characters
"""
def reverse(s): left, right = 0, len(s)-1 while left < right: s[left], s[right] = s[right], s[left] left += 1 right -= 1
別のダブルポインタの古典的な演習は、判決の回文文字列です。文字列に、文字列は、文字列が回文ではありません決定されます。
私たちは、簡単に解決のダブルポインタ演算を使用することができます。
Pythonの:
def isPalindrome(s):
i, j = 0, len(s)-1 while i < j: if s[i] != s[j]: return False i += 1 j -= 1 return True
ダブルポインタの創始者:二つの数字
タイトル説明
整数の配列に、2つの数値を見つけて、ターゲットの特定の数にそれらを等しくします。
これら2つの数値を返します。
Pythonの:
class Solution:
def twoSum(self, numbers, target): numbers.sort() L, R = 0, len(numbers)-1 while L < R: if numbers[L]+numbers[R] == target: return (numbers[L], numbers[R]) if numbers[L]+numbers[R] < target: L += 1 else: R -= 1 return None
- まず、配列をソート。
- (L、R)で始まり、左右2つのポインタ:
- 見つかった場合は番号[L] +数字[R] ==目標、説明、対応する番号を返します。
- もし番号[L] +数字[R] <ターゲット、今回右ポインタL、およびより大きな利用可能にする唯一の方法。
- 逆に、そのRが左。
- LとRには解決策が説明されません見つけることがまだ満たしています。
ダブルポインタ付き
ダブルポインタの問題で、それは二つのポインタが同じ方向に移動し、ゼロから始めているを指します。私たちは、以下の5つのトピックで、二ポインタで予備的な理解に来ます:
- 再発行の配列で重複を削除するアレイ
- ウィンドウ合計スライディングウィンドウの問題
- 二つの数の問題二つの違いの違い
- リスト中点がリンクされたリストの中間を発行します
- ベルトループチェーンの問題リンクリストサイクル
問題の説明
あなたは、配列を与えた後、それは反復要素の除去は、前の配列要素を移動省略する必要とし、要素数が繰り返されていませんが返されます。
:LintCodeは、住所行使http://www.lintcode.com/problem/remove-duplicate-numbers-in-array/
分析
この問題には、2つの方法がありますが、最初のアプローチは、ハッシュテーブルにスローされるすべての数字は、その後、あなたはどの異なる整数を見つけることができると考えるのは簡単です。しかし、このアプローチは余分なスペースを消費するO(N)O(N-)O (N- )。インタビュアーは、余分なスペースを費やすことはないか、聞いてきます。
この時点で、我々は最初の配列をソートし、ダブルポインタ演算を使用する必要があるので、これらのユニークな整数が一緒にプッシュされます。次に、2つのポインタ、いくつかはより速く行く配列全体、さらにポインタを横断ポインタが、現在は常に最後のセクション番号を繰り返すように指していません。別のポインタとポインタのカウントが遅い見つける迅速た後、この数は遅いポインタの後ろの位置に投げ込ますることができ、かつポインタが++遅くします。
#O(nlogn)時間、O(1)余分なスペースの クラス溶液: #1 @param {INT []} NUMS整数のアレイ #1 @return {INT}一意の整数の数 DEF重複排除(自己、NUMS): #書き込みあなたのここでのコード のn = LEN(NUMS) の場合のn == 0: リターン0 nums.sort() 結果= 1 の範囲(1、n)の中に私用: NUMS場合は、[I - 1] = NUMS [I]:! NUMS [結果] = NUMS [i]を 結果+ = 1つの 戻り結果
問題の説明
アレイの各取得KK Kと連続する整数の配列。NUMS =ように[1,2,3,4]
、K = 2
単語、アレイのウィンドウ合計[3,5,7]
。
http://www.lintcode.com/problem/window-sum/
分析
この質問とそこには難しさがありませんが、あなたはあまりにも暴力のユーザーであればO(N * K)O(N- * K)O (N- * K )行うアルゴリズムが適切ではありません。このような現在のウィンドウとしてあります|1,2|,3,4
。ウィンドウを左から右へ移動され、次いで場合1,|2,3|,4
ウィンドウ全体及び3の整数1を減少させる、増加させた場合。変更する整数Aに、スライディングウィンドウのプロセス全体をシミュレートすることが必要なだけです。これは、スライディングウィンドウの問題です。
クラス溶液: #1 @paramのNUMS {INT []}整数のリスト ウィンドウの#の@paramのK {INT}サイズ #1 @return {INT []}各移動におけるウィンドウ内の要素の和 winSum DEF(自己、NUMS 、K): #ここにコードを書く N = LEN(NUMS) :もしN <KまたはK <= 0 を返す[] - K + 1)の和= [0] *(N :範囲(K)におけるiについて 合計を[0] + = NUMS [I]。 : - (K + 1、N)Iの範囲内のための 合計[i]は=合計[I - 1] - NUMS [I - 1] + NUMS [I + K - 1] 戻り和
2つの数の問題との違い
610番号2つは - 目標値に等しいです
整数の配列を指定し、2つの数値を見つけることは差
、目標値に等しいです。インデックス1はINDEX2未満でなければなりません。インデックス1とINDEX2のリターンは0ベースではないことに注意してください。
サンプル
例1:
输入: nums = [2, 7, 15, 24], target = 5
输出: [1, 2]
解释:
(7 - 2 = 5)
例2:
输入: nums = [1, 1], target = 0
输出: [1, 2]
解释:
(1 - 1 = 0)
注意事項
唯一の答えがあることを確認してください。
分析
問題と二つの数字、二つの数字と悪い面接の質問には、後に頼まれたとしてフォローアップ、2数の差が頻繁に発生します。
NUMS [ -でも、アレイにすでに前提、NUMS [i]がソートされているので、私たちはまず、試してみて、二つの方法の数と動作しないことが判明することができます j]をターゲットとの間の関係と、我々は排除を決定することはできませんNUMS [I]またはNUMS [J]。
だから我々はNUMSに両手の代わりに、互いに途中、私のポインタを進めることを試みる[i]は、jのポインタが最初にするNUMS [J] - NUMS [I]> = |ターゲット|の添字J:
- NUMS [j]の場合 - NUMS [i]を== |ターゲット|、そして答えを見つけます
- そうでなければ、私たちは私を移動しようと、私は> =右に移動をする++
- 我々はまた、NUMS [J]まで、右に移動します。この時点でJ - NUMS [I]> = |目標|
私たちは、j個の移動のためにゼロからスタートしないことを知ることができますが、下に移動高まってきているので、この時間は、iとjの間に2つのサイクルは、乗法関係なく、重畳関係ではありません。
Pythonの:
nums.sort()
target = abs(target)
j = 1
for i in range(len(nums)):
while j < len(nums) and nums[j]-nums[i] < target: j += 1 if nums[j]-nums[i] == target: # 找到答案
クラス溶液: "" " @paramのNUMS:整数のアレイ @paramターゲット:整数 @return:[index1の+ 1、INDEX2 + 1](index1の<INDEX2) """ DEF twoSum7(自己、NUMS、ターゲット) #ここにコードを書く = ABS(標的)を標的 nums2 = [(N、I)I、N列挙で(NUMS)のために] nums2.sort(キー=ラムダX:X [0]) 結果= [] J = 1 (LEN(nums2))の範囲内の私が しばらくJ <LEN(nums2)とnums2 [J] [0] -nums2 [I] [0] <目標: J + = 1 であればnums2 [j] [0] - nums2 [I] [0] ==目標: もし私= J!: 結果=(nums2 [I] [1] +1、nums2 [J] [1] +1) ブレーク 結果[0]>結果は[1]の場合: リターン[結果[1]、[0]結果] リターン結果
同様の問題
同様の質問のGファミリー:多くはタプルの配列を見つける方法、その二乗差が<ターゲット(目標は正の整数です)。
私たちは、最初の配列のそれぞれを二乗し、解決するために同様の方法を置くことができ、その後の質問は、<ターゲット2数の差のどのくらいになります。
そして、ペアNUMS [j]を見つけたときに、このプロセスの上に行く- NUMS [I]> =ターゲット、彼らは1人の息の同等のものを見つけたとき:
nums[i + 1] - nums[i]
nums[i + 2] - nums[i]
...
nums[j - 1] - nums[i]
合計j - i - 1
要件を満たすためにタプル。累積カウントは、その後、私は1を+位置に移動します。
中間点の問題を一覧表示します
問題の説明
リンクリストの中点を探します
:LintCodeは、住所行使http://www.lintcode.com/problem/middle-of-linked-list/
リストの中間点228
リストの中間点を見つけます。
サンプル
例1:
输入: 1->2->3
输出: 2
样例解释: 返回中间节点的值
サンプル2:
输入: 1->2
输出: 1
样例解释: 如果长度是偶数,则返回中间偏左的节点的值。
挑戦
リストには、データストリームである場合は、リンクリストトラバース中間点を再せずにそれを得ることができますか?
"" " ListNodeの定義の クラスListNode(オブジェクト): デフ__init __(自己、ヴァル、次=なし): self.val = valの self.next =次 """ クラスのソリューション :""」 @paramヘッド:の頭。リンクリスト @return:リンクリストの中間ノード 「」」 DEF middleNode(自己、頭): #ここにあなたのコードを書く 遅い、速い=頭部、頭 ながら、迅速かつfast.nextとfast.next.next: 遅いです= slow.next = fast.next.next速い 遅い戻ります
これは、fast.next.next条件は、全体で前方に2つのステップを表すことができます。
分析
私たちが感じることの質問は、WTFはこれを行うに勝るものは、単純なありませんか?あなたは思考することができます。
最初にL / 2の位置にあるノードを見つけるためにリストをトラバースし、次いで、リスト全体を横切る長さLを見つけ、そして見えます。
あなたはこのアイデアを投げた後、しかし、インタビュアーはあなたを尋ねてきます。如果只允许遍历链表一次怎么办?
これはあなたがアルゴリズムの時間の複雑さを最適化させないで見ることができるフォローアップ、厳密にあなたはリスト全体をトラバース回数が制限されます。あなたは、これはそれを最適化するために理にかなっていると思うかもしれませんか?実際には理にかなっています。ので遍历一次
、このシナリオでは、多くの場合、つまり、私たちはしばしば言う、実際のエンジニアリング環境で発生します数据流问题
(データストリームの問題)。
データフロー問題データストリームの問題
いわゆるデータフローの問題、つまり、あなたが継続的にいくつかのデータを受信し、オンラインシステムを設計する必要がある、とのデータとの情報の一部を保持しています。たとえば、この問題はそれが中間点を維持するために、データストリームです。(メンテナンスの中点は、その中点を取得するためのインタフェースを提供する手段)
同様の問題だけでなく、データ・ストリームの一部:
- 中央値のデータ・ストリームhttp://www.lintcode.com/problem/data-stream-median/
- K最大データフローアイテムhttp://www.lintcode.com/problem/top-k-largest-numbers-ii/
- K-周波数ストリームデータ項目http://www.lintcode.com/problem/top-k-frequent-words-ii/
このような質問の特徴は、あなたです没有机会第二次遍历所有数据
。上記の問題の一部は、の「9章アルゴリズム集中講義」で説明されます。
ダブルポインタリスト中点アルゴリズムの解決の問題
我々は呼び出すことができ、より具体的には、リストの中間点の問題を解決するために、ダブルポインタ演算を使用することができる快慢指针
アルゴリズムを。次のようなアルゴリズムは次のようになります。
Pythonの:
slow, fast = head, head.next
while fast != None and fast.next != None:
slow = slow.next
fast = fast.next.next
return slow
各ループの2つのステップを行くための高速手、低速のポインタがさらに一歩進めながら、上記のプログラムでは、我々はすぐに、2番目のノードで最初のノードの遅いポインタをポインタます。中間点の時に遅いポインタポインタが速く終わりに近づいているときようにします。
「ベルトループ・チェーン」の次のセクションのポインタ速度アルゴリズムも使用します。======> 文言のエラーが発生しやすい、私の期待感は、2つのステップがより良いアプローチ取ることができます!
小さな運動
インターフェイスモードを提供するために上記のコード、すなわち、設計クラス、二つの機能をサポートし、一方があるadd(node)
ノードを追加すること、であるgetMiddle()
その中間ノード要求。
102ベルトループチェーン
リストを考えると、リングがあるか否かを判断します。
サンプル
```
样例 1:
输入: 21->10->4->5, then tail connects to node index 1(value 10).
输出: true
样例 2:
输入: 21->10->4->5->null
输出: false
```
挑戦
余分なスペースを使用しないでください
"" " ListNodeの定義の クラスListNode(オブジェクト): デフ__init __(自己、ヴァル、次=なし): self.val = valの self.next =次 """ クラスのソリューション :""」 @paramヘッド:の頭。リンクリスト @return:リンクリストの中間ノード 「」」 DEF middleNode(自己、頭): #ここにあなたのコードを書く 遅い、速い=頭部、頭 ながら、迅速かつfast.nextとfast.next.next: 遅いです= slow.next = fast.next.next速い 遅い戻ります
二つの古典的なソートアルゴリズム
クイックソート(クイックソート)とマージソート(並び替えをマージ)2つの基礎ポイントアルゴリズム必修インタビューです。多くのアルゴリズムインタビューの質問、直接2つのアルゴリズムを求めて、これら2つのアルゴリズムを選び出すために同じ考えのこれら2つのアルゴリズムや実装のいずれかの、いずれかを使用して、これら2つのアルゴリズムのいずれかを変更します調査するためのいくつかのステップ。